The default thread count is currently 4 and it is also configurable via --threads/-t paramter for the libvirt-dbus daemon. Signed-off-by: Pavel Hrdina <phrdina@xxxxxxxxxx> --- src/connect.c | 4 +++ src/connect.h | 1 + src/gdbus.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++------------- src/gdbus.h | 4 +++ src/main.c | 10 ++++++ 5 files changed, 95 insertions(+), 21 deletions(-) diff --git a/src/connect.c b/src/connect.c index a3b1cf2..8363a4d 100644 --- a/src/connect.c +++ b/src/connect.c @@ -56,6 +56,8 @@ gboolean virtDBusConnectOpen(virtDBusConnect *connect, GError **error) { + g_autoptr(GMutexLocker) lock = g_mutex_locker_new(&connect->lock); + if (connect->connection) { if (virConnectIsAlive(connect->connection)) return TRUE; @@ -211,6 +213,8 @@ virtDBusConnectNew(virtDBusConnect **connectp, connect = g_new0(virtDBusConnect, 1); g_assert(connect != NULL); + g_mutex_init(&connect->lock); + for (gint i = 0; i < VIR_DOMAIN_EVENT_ID_LAST; i += 1) connect->callback_ids[i] = -1; diff --git a/src/connect.h b/src/connect.h index f8b1d06..17792cd 100644 --- a/src/connect.h +++ b/src/connect.h @@ -14,6 +14,7 @@ struct virtDBusConnect { const gchar *connectPath; gchar *domainPath; virConnectPtr connection; + GMutex lock; gint callback_ids[VIR_DOMAIN_EVENT_ID_LAST]; }; diff --git a/src/gdbus.c b/src/gdbus.c index 7dd5766..76f0df6 100644 --- a/src/gdbus.c +++ b/src/gdbus.c @@ -15,6 +15,16 @@ struct _virtDBusGDBusSubtreeData { }; typedef struct _virtDBusGDBusSubtreeData virtDBusGDBusSubtreeData; +struct _virtDBusGDBusThreadData { + const gchar *objectPath; + const gchar *interfaceName; + const gchar *methodName; + GVariant *parameters; + GDBusMethodInvocation *invocation; + virtDBusGDBusMethodData *methodData; +}; +typedef struct _virtDBusGDBusThreadData virtDBusGDBusThreadData; + static const gchar *dbusInterfacePrefix = NULL; /** @@ -221,6 +231,38 @@ virtDBusGDBusHandleMethod(GVariant *parameters, outFDs); } +static void +virtDBusGDBusMethodCallThread(gpointer threadData, + gpointer userData G_GNUC_UNUSED) +{ + g_autofree virtDBusGDBusThreadData *data = threadData; + + if (g_strcmp0(data->interfaceName, "org.freedesktop.DBus.Properties") == 0) { + if (g_strcmp0(data->methodName, "Get") == 0) { + virtDBusGDBusHandlePropertyGet(data->parameters, data->invocation, + data->objectPath, data->methodData); + } else if (g_strcmp0(data->methodName, "Set") == 0) { + virtDBusGDBusHandlePropertySet(data->parameters, data->invocation, + data->objectPath, data->methodData); + } else if (g_strcmp0(data->methodName, "GetAll") == 0) { + virtDBusGDBusHandlePropertyGetAll(data->invocation, data->objectPath, + data->methodData); + } else { + g_dbus_method_invocation_return_error(data->invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_UNKNOWN_METHOD, + "unknown method '%s'", + data->methodName); + } + } else { + virtDBusGDBusHandleMethod(data->parameters, data->invocation, + data->objectPath, data->methodName, + data->methodData); + } +} + +GThreadPool *threadPool; + static void virtDBusGDBusHandleMethodCall(GDBusConnection *connection G_GNUC_UNUSED, const gchar *sender G_GNUC_UNUSED, @@ -231,27 +273,18 @@ virtDBusGDBusHandleMethodCall(GDBusConnection *connection G_GNUC_UNUSED, GDBusMethodInvocation *invocation, gpointer userData) { - virtDBusGDBusMethodData *data = userData; - - if (g_strcmp0(interfaceName, "org.freedesktop.DBus.Properties") == 0) { - if (g_strcmp0(methodName, "Get") == 0) { - virtDBusGDBusHandlePropertyGet(parameters, invocation, - objectPath, data); - } else if (g_strcmp0(methodName, "Set") == 0) { - virtDBusGDBusHandlePropertySet(parameters, invocation, - objectPath, data); - } else if (g_strcmp0(methodName, "GetAll") == 0) { - virtDBusGDBusHandlePropertyGetAll(invocation, objectPath, data); - } else { - g_dbus_method_invocation_return_error(invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_UNKNOWN_METHOD, - "unknown method '%s'", methodName); - } - } else { - virtDBusGDBusHandleMethod(parameters, invocation, objectPath, - methodName, data); - } + virtDBusGDBusThreadData *data = g_new0(virtDBusGDBusThreadData, 1); + + g_assert(data); + + data->objectPath = objectPath; + data->interfaceName = interfaceName; + data->methodName = methodName; + data->parameters = parameters; + data->invocation = invocation; + data->methodData = userData; + + g_thread_pool_push(threadPool, data, NULL); } static const GDBusInterfaceVTable virtDBusGDBusVtable = { @@ -391,3 +424,25 @@ virtDBusGDBusRegisterSubtree(GDBusConnection *bus, virtDBusGDBusSubtreeDataFree, NULL); } + +/** + * virtDBusGDBusPrepareThreadPool: + * @maxThreads: the number of maximum threads in thread pool + * @error: return location for error or NULL + * + * Initializes thread pool to be used to process D-Bus messages. + * + * Returns TRUE on success, FALSE on error and sets @error. + */ +gboolean +virtDBusGDBusPrepareThreadPool(gint maxThreads, + GError **error) +{ + threadPool = g_thread_pool_new(virtDBusGDBusMethodCallThread, + NULL, + maxThreads, + FALSE, + error); + + return !!threadPool; +} diff --git a/src/gdbus.h b/src/gdbus.h index 21ee6fc..05e6527 100644 --- a/src/gdbus.h +++ b/src/gdbus.h @@ -91,5 +91,9 @@ virtDBusGDBusRegisterSubtree(GDBusConnection *bus, virtDBusGDBusPropertyTable *properties, gpointer userData); +gboolean +virtDBusGDBusPrepareThreadPool(gint maxThreads, + GError **error); + G_DEFINE_AUTO_CLEANUP_FREE_FUNC(virtDBusGDBusSource, g_source_remove, 0); G_DEFINE_AUTO_CLEANUP_FREE_FUNC(virtDBusGDBusOwner, g_bus_unown_name, 0); diff --git a/src/main.c b/src/main.c index 2991075..70e5902 100644 --- a/src/main.c +++ b/src/main.c @@ -83,11 +83,14 @@ virtDBusRegisterDataFree(virtDBusRegisterData *data) } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(virtDBusRegisterData, virtDBusRegisterDataFree); +#define VIRT_DBUS_MAX_THREADS 4 + int main(gint argc, gchar *argv[]) { static gboolean systemOpt = FALSE; static gboolean sessionOpt = FALSE; + static gint maxThreads = VIRT_DBUS_MAX_THREADS; GBusType busType; g_auto(virtDBusGDBusSource) sigintSource = 0; g_auto(virtDBusGDBusSource) sigtermSource = 0; @@ -102,6 +105,8 @@ main(gint argc, gchar *argv[]) "Connect to the system bus", NULL }, { "session", 0, 0, G_OPTION_ARG_NONE, &sessionOpt, "Connect to the session bus", NULL }, + { "threads", 't', 0, G_OPTION_ARG_INT, &maxThreads, + "Configure maximal number of worker threads", "N" }, { NULL } }; @@ -140,6 +145,11 @@ main(gint argc, gchar *argv[]) data.connectList = g_new0(virtDBusConnect *, data.ndrivers + 1); g_assert(data.connectList); + if (!virtDBusGDBusPrepareThreadPool(maxThreads, &error)) { + g_printerr("%s\n", error->message); + exit(EXIT_FAILURE); + } + loop = g_main_loop_new(NULL, FALSE); sigtermSource = g_unix_signal_add(SIGTERM, -- 2.14.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list