common: Add ProxyPool for dbus method call 24/106724/1 accepted/tizen_3.0.m2_mobile accepted/tizen_3.0.m2_tv accepted/tizen_3.0.m2_wearable tizen_3.0.m2 accepted/tizen/3.0.m2/mobile/20170104.100232 accepted/tizen/3.0.m2/tv/20170104.100418 accepted/tizen/3.0.m2/wearable/20170104.101007 accepted/tizen/3.0/common/20161227.101336 accepted/tizen/3.0/ivi/20161226.025036 accepted/tizen/3.0/mobile/20161226.024944 accepted/tizen/3.0/tv/20161226.024959 accepted/tizen/3.0/wearable/20161226.025013 submit/tizen_3.0.m2/20170104.093748 submit/tizen_3.0/20161222.072356
authorpr.jung <pr.jung@samsung.com>
Thu, 22 Dec 2016 13:09:14 +0000 (22:09 +0900)
committerpr.jung <pr.jung@samsung.com>
Thu, 22 Dec 2016 13:09:14 +0000 (22:09 +0900)
- Reuse proxy for same destination and interface

Change-Id: I89a57e81afb0a7eb386067671704acd7d805550b
Signed-off-by: pr.jung <pr.jung@samsung.com>
src/dbus.c

index b5d5757..e49e71b 100644 (file)
 
 #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;
 }