From nobody Sun May 5 21:53:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1521548119798896.7029368489654; Tue, 20 Mar 2018 05:15:19 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4224033BE9; Tue, 20 Mar 2018 12:15:18 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 122855DA62; Tue, 20 Mar 2018 12:15:18 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id C6628181B9FF; Tue, 20 Mar 2018 12:15:17 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w2KCFGUB028429 for ; Tue, 20 Mar 2018 08:15:16 -0400 Received: by smtp.corp.redhat.com (Postfix) id 85EF4200BCAE; Tue, 20 Mar 2018 12:15:16 +0000 (UTC) Received: from antique-work.brq.redhat.com (unknown [10.43.2.152]) by smtp.corp.redhat.com (Postfix) with ESMTP id E816F2022C02 for ; Tue, 20 Mar 2018 12:15:15 +0000 (UTC) From: Pavel Hrdina To: libvir-list@redhat.com Date: Tue, 20 Mar 2018 13:15:12 +0100 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-loop: libvir-list@redhat.com Subject: [libvirt] [dbus PATCH v2 1/3] introduce support for GDBus implementation X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 20 Mar 2018 12:15:18 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" We will switch to GDBus implementation of D-Bus protocol because sd-bus implementation is not thread safe. Processing messages in threads is essential since Libvirt API can take some significant amount of time to return and that would block the whole libvirt-dbus daemon. Signed-off-by: Pavel Hrdina --- Changes in v2: - changed glib2 required version to 2.44.0, required for the auto-cleanup macros - changed libvirt-glib required version to 0.0.7 README | 1 + configure.ac | 12 ++ data/Makefile.am | 5 + libvirt-dbus.spec.in | 6 + src/Makefile.am | 17 ++- src/gdbus.c | 401 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ src/gdbus.h | 107 ++++++++++++++ test/Makefile.am | 3 +- test/travis-run | 2 +- 9 files changed, 549 insertions(+), 5 deletions(-) create mode 100644 src/gdbus.c create mode 100644 src/gdbus.h diff --git a/README b/README index 754d957..a85114e 100644 --- a/README +++ b/README @@ -58,6 +58,7 @@ The packages required to build libvirt-dbus are =20 - systemd-211 - libvirt + - glib2 =20 Patches submissions =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D diff --git a/configure.ac b/configure.ac index df1a375..0e3bc01 100644 --- a/configure.ac +++ b/configure.ac @@ -11,10 +11,14 @@ AC_USE_SYSTEM_EXTENSIONS =20 AM_SILENT_RULES([yes]) =20 +GLIB2_REQUIRED=3D2.44.0 LIBVIRT_REQUIRED=3D1.2.8 SYSTEMD_REQUIRED=3D211 +LIBVIRT_GLIB_REQUIRED=3D0.0.7 +AC_SUBST([GLIB2_REQUIRED]) dnl used in the .spec file AC_SUBST([LIBVIRT_REQUIRED]) dnl used in the .spec file AC_SUBST([SYSTEMD_REQUIRED]) dnl used in the .spec file +AC_SUBST([LIBVIRT_GLIB_REQUIRED]) dnl used in the .spec file =20 LIBVIRT_DBUS_MAJOR_VERSION=3D`echo $VERSION | awk -F. '{print $1}'` LIBVIRT_DBUS_MINOR_VERSION=3D`echo $VERSION | awk -F. '{print $2}'` @@ -34,8 +38,11 @@ AC_PROG_MKDIR_P AM_PROG_CC_C_O AC_PROG_CC_STDC =20 +PKG_CHECK_MODULES(GIO2, gio-unix-2.0 >=3D GLIB2_REQUIRED) +PKG_CHECK_MODULES(GLIB2, glib-2.0 >=3D GLIB2_REQUIRED) PKG_CHECK_MODULES(LIBVIRT, libvirt >=3D $LIBVIRT_REQUIRED) PKG_CHECK_MODULES(SYSTEMD, libsystemd >=3D $SYSTEMD_REQUIRED) +PKG_CHECK_MODULES(LIBVIRT_GLIB, libvirt-glib-1.0 >=3D LIBVIRT_GLIB_REQUIRE= D) =20 LIBVIRT_COMPILE_WARNINGS LIBVIRT_LINKER_RELRO @@ -56,6 +63,11 @@ LIBVIRT_ARG_WITH([DBUS_SYSTEM_POLICIES], [where D-Bus sy= stem policies directory DBUS_SYSTEM_POLICIES_DIR=3D"$with_dbus_system_policies" AC_SUBST(DBUS_SYSTEM_POLICIES_DIR) =20 +LIBVIRT_ARG_WITH([DBUS_INTERFACES], [where D-Bus interfaces directory is], + ['$(datadir)/dbus-1/interfaces']) +DBUS_INTERFACES_DIR=3D"$with_dbus_interfaces" +AC_SUBST([DBUS_INTERFACES_DIR]) + LIBVIRT_ARG_WITH([SYSTEM_USER], [username to run system instance as], ['libvirtdbus']) SYSTEM_USER=3D$with_system_user diff --git a/data/Makefile.am b/data/Makefile.am index 9a53305..a886687 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -18,11 +18,16 @@ polkit_files =3D \ polkitdir =3D $(sysconfdir)/polkit-1/rules.d polkit_DATA =3D $(polkit_files:.rules.in=3D.rules) =20 +interfaces_files =3D +interfacesdir =3D $(DBUS_INTERFACES_DIR) +interfaces_DATA =3D $(interfaces_files) + EXTRA_DIST =3D \ $(service_in_files) \ $(system_service_in_files) \ $(system_policy_files) \ $(polkit_files) \ + $(interfaces_files) \ $(NULL) =20 CLEANFILES =3D \ diff --git a/libvirt-dbus.spec.in b/libvirt-dbus.spec.in index ce5cecf..662ece1 100644 --- a/libvirt-dbus.spec.in +++ b/libvirt-dbus.spec.in @@ -1,7 +1,9 @@ # -*- rpm-spec -*- =20 +%define glib2_version @GLIB2_REQUIRED@ %define libvirt_version @LIBVIRT_REQUIRED@ %define systemd_version @SYSTEMD_REQUIRED@ +%define libvirt_glib_version @LIBVIRT_GLIB_REQUIRED@ %define system_user @SYSTEM_USER@ =20 Name: @PACKAGE@ @@ -15,11 +17,15 @@ Source0: ftp://libvirt.org/libvirt/dbus/%{name}-%{versi= on}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) =20 BuildRequires: gcc +BuildRequires: glib2-devel >=3D %{glib2_version} BuildRequires: libvirt-devel >=3D %{libvirt_version} BuildRequires: systemd-devel >=3D %{systemd_version} +BuildRequires: libvirt-glib-devel >=3D %{libvirt_glib_version} =20 +Requires: glib2 >=3D %{glib2_version} Requires: libvirt-libs >=3D %{libvirt_version} Requires: systemd-libs >=3D %{systemd_version} +Requires: libvirt-glib >=3D %{libvirt_glib_version} =20 Requires(pre): shadow-utils =20 diff --git a/src/Makefile.am b/src/Makefile.am index 1a5b50b..e7bba9d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,12 +1,14 @@ AM_CPPFLAGS =3D \ - -I$(top_srcdir)/src + -I$(top_srcdir)/src \ + -DVIRT_DBUS_INTERFACES_DIR=3D\"$(DBUS_INTERFACES_DIR)\" =20 DAEMON_SOURCES =3D \ main.c \ connect.c connect.h \ util.c util.h \ domain.c domain.h \ - events.c events.h + events.c events.h \ + gdbus.c gdbus.h =20 EXTRA_DIST =3D \ $(DAEMON_SOURCES) @@ -18,18 +20,27 @@ libvirt_dbus_SOURCES =3D $(DAEMON_SOURCES) =20 libvirt_dbus_CFLAGS =3D \ $(SYSTEMD_CFLAGS) \ + $(GIO2_CFLAGS) \ + $(GLIB2_CFLAGS) \ $(LIBVIRT_CFLAGS) \ + $(LIBVIRT_GLIB_CFLAGS) \ $(WARN_CFLAGS) \ $(PIE_CFLAGS) \ $(NULL) =20 libvirt_dbus_LDFLAGS =3D \ $(SYSTEMD_LDFLAGS) \ + $(GIO2_LDFLAGS) \ + $(GLIB2_LDFLAGS) \ $(LIBVIRT_LDFLAGS) \ + $(LIBVIRT_GLIB_LDFLAGS) \ $(RELRO_LDFLAGS) \ $(PID_LDFLAGS) \ $(NULL) =20 libvirt_dbus_LDADD =3D \ $(SYSTEMD_LIBS) \ - $(LIBVIRT_LIBS) + $(GIO2_LIBS) \ + $(GLIB2_LIBS) \ + $(LIBVIRT_LIBS) \ + $(LIBVIRT_GLIB_LIBS) diff --git a/src/gdbus.c b/src/gdbus.c new file mode 100644 index 0000000..de02415 --- /dev/null +++ b/src/gdbus.c @@ -0,0 +1,401 @@ +#include "gdbus.h" + +#include + +struct _virtDBusGDBusMethodData { + virtDBusGDBusMethodTable *methods; + virtDBusGDBusPropertyTable *properties; + gpointer *userData; +}; +typedef struct _virtDBusGDBusMethodData virtDBusGDBusMethodData; + +struct _virtDBusGDBusSubtreeData { + GDBusInterfaceInfo *interface; + virtDBusGDBusEnumerateFunc enumerate; + virtDBusGDBusMethodData *methodData; +}; +typedef struct _virtDBusGDBusSubtreeData virtDBusGDBusSubtreeData; + +static const gchar *dbusInterfacePrefix =3D NULL; + +/** + * virtDBusGDBusLoadIntrospectData: + * @interface: name of the interface + * + * Reads an interface XML description from file and returns new + * interface info. The caller owns an reference to the returned info. + * + * The file path is constructed as: + * + * VIRT_DBUS_INTERFACES_DIR/{@interface}.xml + * + * Returns interface info on success, NULL on failure. + */ +GDBusInterfaceInfo * +virtDBusGDBusLoadIntrospectData(gchar const *interface) +{ + g_autofree gchar *introspectFile =3D NULL; + g_autofree gchar *introspectXML =3D NULL; + g_autoptr(GDBusNodeInfo) nodeInfo =3D NULL; + GDBusInterfaceInfo *ret; + + if (!dbusInterfacePrefix) { + dbusInterfacePrefix =3D g_getenv("VIRT_DBUS_INTERFACES_DIR"); + if (!dbusInterfacePrefix) + dbusInterfacePrefix =3D VIRT_DBUS_INTERFACES_DIR; + } + + introspectFile =3D g_strdup_printf("%s/%s.xml", dbusInterfacePrefix, i= nterface); + g_assert(introspectFile !=3D NULL); + + g_file_get_contents(introspectFile, &introspectXML, NULL, NULL); + g_assert(introspectXML !=3D NULL); + + nodeInfo =3D g_dbus_node_info_new_for_xml(introspectXML, NULL); + if (!nodeInfo) + return NULL; + + ret =3D nodeInfo->interfaces[0]; + if (!ret) + return NULL; + + return g_dbus_interface_info_ref(ret); +} + +static void +virtDBusGDBusHandlePropertyGet(GVariant *parameters, + GDBusMethodInvocation *invocation, + const gchar *objectPath, + virtDBusGDBusMethodData *data) +{ + virtDBusGDBusPropertyGetFunc getFunc =3D NULL; + const gchar *interface; + const gchar *name; + GVariant *value =3D NULL; + GError *error =3D NULL; + + g_variant_get(parameters, "(&s&s)", &interface, &name); + + for (gint i =3D 0; data->properties[i].name; i++) { + if (g_strcmp0(name, data->properties[i].name) =3D=3D 0) { + getFunc =3D data->properties[i].getFunc; + break; + } + } + + if (!getFunc) { + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_UNKNOWN_PROPERT= Y, + "unknown property '%s'", nam= e); + return; + } + + getFunc(objectPath, data->userData, &value, &error); + + if (error) { + g_dbus_method_invocation_return_gerror(invocation, error); + return; + } + + g_return_if_fail(value); + + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(v)", value)); +} + +static void +virtDBusGDBusHandlePropertySet(GVariant *parameters, + GDBusMethodInvocation *invocation, + const gchar *objectPath, + virtDBusGDBusMethodData *data) +{ + virtDBusGDBusPropertySetFunc setFunc =3D NULL; + const gchar *interface; + const gchar *name; + g_autoptr(GVariant) value =3D NULL; + GError *error =3D NULL; + + g_variant_get(parameters, "(&s&sv)", &interface, &name, &value); + + for (gint i =3D 0; data->properties[i].name; i++) { + if (g_strcmp0(name, data->properties[i].name) =3D=3D 0) { + setFunc =3D data->properties[i].setFunc; + break; + } + } + + if (!setFunc) { + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_UNKNOWN_PROPERT= Y, + "unknown property '%s'", nam= e); + return; + } + + setFunc(value, objectPath, data->userData, &error); + + if (error) + g_dbus_method_invocation_return_gerror(invocation, error); + else + g_dbus_method_invocation_return_value(invocation, NULL); +} + +static void +virtDBusGDBusHandlePropertyGetAll(GDBusMethodInvocation *invocation, + const gchar *objectPath, + virtDBusGDBusMethodData *data) +{ + GVariant *value; + g_auto(GVariantBuilder) builder; + GError *error =3D NULL; + + g_variant_builder_init(&builder, G_VARIANT_TYPE("(a{sv})")); + + g_variant_builder_open(&builder, G_VARIANT_TYPE("a{sv}")); + + for (gint i =3D 0; data->properties[i].name; i++) { + data->properties[i].getFunc(objectPath, data->userData, + &value, &error); + + if (error) { + g_dbus_method_invocation_return_gerror(invocation, error); + return; + } + + g_return_if_fail(value); + + g_variant_builder_add(&builder, "{sv}", + data->properties[i].name, + g_variant_new_variant(value)); + } + + g_variant_builder_close(&builder); + + g_dbus_method_invocation_return_value(invocation, + g_variant_builder_end(&builder)); +} + +static void +virtDBusGDBusHandleMethod(GVariant *parameters, + GDBusMethodInvocation *invocation, + const gchar *objectPath, + const gchar *methodName, + virtDBusGDBusMethodData *data) +{ + virtDBusGDBusMethodFunc methodFunc =3D NULL; + GDBusMessage *msg =3D g_dbus_method_invocation_get_message(invocation); + GUnixFDList *inFDs =3D NULL; + GVariant *outArgs =3D NULL; + GUnixFDList *outFDs =3D NULL; + GError *error =3D NULL; + + for (gint i =3D 0; data->methods[i].name; i++) { + if (g_strcmp0(methodName, data->methods[i].name) =3D=3D 0) { + methodFunc =3D data->methods[i].methodFunc; + break; + } + } + + if (!methodFunc) { + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_UNKNOWN_METHOD, + "unknown method '%s'", metho= dName); + return; + } + + inFDs =3D g_dbus_message_get_unix_fd_list(msg); + + methodFunc(parameters, inFDs, objectPath, data->userData, + &outArgs, &outFDs, &error); + + if (error) { + g_dbus_method_invocation_return_gerror(invocation, error); + return; + } + + g_return_if_fail(outArgs || !outFDs); + + g_dbus_method_invocation_return_value_with_unix_fd_list(invocation, + outArgs, + outFDs); +} + +static void +virtDBusGDBusHandleMethodCall(GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *objectPath, + const gchar *interfaceName, + const gchar *methodName, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer userData) +{ + virtDBusGDBusMethodData *data =3D userData; + + if (g_strcmp0(interfaceName, "org.freedesktop.DBus.Properties") =3D=3D= 0) { + if (g_strcmp0(methodName, "Get") =3D=3D 0) { + virtDBusGDBusHandlePropertyGet(parameters, invocation, + objectPath, data); + } else if (g_strcmp0(methodName, "Set") =3D=3D 0) { + virtDBusGDBusHandlePropertySet(parameters, invocation, + objectPath, data); + } else if (g_strcmp0(methodName, "GetAll") =3D=3D 0) { + virtDBusGDBusHandlePropertyGetAll(invocation, objectPath, data= ); + } else { + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_UNKNOWN_MET= HOD, + "unknown method '%s'", m= ethodName); + } + } else { + virtDBusGDBusHandleMethod(parameters, invocation, objectPath, + methodName, data); + } +} + +static const GDBusInterfaceVTable virtDBusGDBusVtable =3D { + virtDBusGDBusHandleMethodCall, + NULL, + NULL, + { NULL } +}; + +/** + * virtDBusGDBusRegisterObject: + * @bus: GDBus connection + * @objectPath: object path + * @interface: interface info of the object + * @methods: table of method handlers + * @properties: table of property handlers + * @userData: data that are passed to method and property handlers + * + * Registers a new D-Bus object that we would like to handle. + */ +void +virtDBusGDBusRegisterObject(GDBusConnection *bus, + gchar const *objectPath, + GDBusInterfaceInfo *interface, + virtDBusGDBusMethodTable *methods, + virtDBusGDBusPropertyTable *properties, + gpointer userData) +{ + virtDBusGDBusMethodData *data =3D g_new0(virtDBusGDBusMethodData, 1); + + g_assert(data); + + data->methods =3D methods; + data->properties =3D properties; + data->userData =3D userData; + + g_dbus_connection_register_object(bus, + objectPath, + interface, + &virtDBusGDBusVtable, + data, g_free, + NULL); +} + +static gchar ** +virtDBusGDBusEnumerate(GDBusConnection *connection G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData) +{ + virtDBusGDBusSubtreeData *data =3D userData; + + if (data->enumerate) + return data->enumerate(data->methodData->userData); + + return NULL; +} + +static GDBusInterfaceInfo ** +virtDBusGDBusIntrospect(GDBusConnection *bus G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + const gchar *node G_GNUC_UNUSED, + gpointer userData) +{ + virtDBusGDBusSubtreeData *data =3D userData; + GDBusInterfaceInfo **ret =3D g_new0(GDBusInterfaceInfo *, 2); + + g_assert(ret); + ret[0] =3D g_dbus_interface_info_ref(data->interface); + + return ret; +} + +static const GDBusInterfaceVTable * +virtDBusGDBusDispatch(GDBusConnection *bus G_GNUC_UNUSED, + const gchar *sender G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + const gchar *interfaceName G_GNUC_UNUSED, + const gchar *node G_GNUC_UNUSED, + gpointer *outUserData, + gpointer userData) +{ + virtDBusGDBusSubtreeData *data =3D userData; + + *outUserData =3D data->methodData; + return &virtDBusGDBusVtable; +} + +static const GDBusSubtreeVTable virtDBusGDBusSubreeVtable =3D { + virtDBusGDBusEnumerate, + virtDBusGDBusIntrospect, + virtDBusGDBusDispatch, + { NULL } +}; + +static void +virtDBusGDBusSubtreeDataFree(gpointer opaque) +{ + virtDBusGDBusSubtreeData *data =3D opaque; + g_free(data->methodData); + g_free(data); +} + +/** + * virtDBusGDBusRegisterSubtree: + * @bus: GDBus connection + * @objectPath: object prefix path + * @interface: interface info of the object + * @methods: table of method handlers + * @properties: table of property handlers + * @userData: data that are passed to method and property handlers + * + * Registers a new D-Bus object prefix that we would like to handle. + */ +void +virtDBusGDBusRegisterSubtree(GDBusConnection *bus, + gchar const *objectPath, + GDBusInterfaceInfo *interface, + virtDBusGDBusEnumerateFunc enumerate, + virtDBusGDBusMethodTable *methods, + virtDBusGDBusPropertyTable *properties, + gpointer userData) +{ + virtDBusGDBusSubtreeData *data =3D g_new0(virtDBusGDBusSubtreeData, 1); + + g_assert(data); + + data->methodData =3D g_new0(virtDBusGDBusMethodData, 1); + + g_assert(data->methodData); + + data->interface =3D interface; + data->enumerate =3D enumerate; + data->methodData->methods =3D methods; + data->methodData->properties =3D properties; + data->methodData->userData =3D userData; + + g_dbus_connection_register_subtree(bus, + objectPath, + &virtDBusGDBusSubreeVtable, + G_DBUS_SUBTREE_FLAGS_DISPATCH_TO_UN= ENUMERATED_NODES, + data, + virtDBusGDBusSubtreeDataFree, + NULL); +} diff --git a/src/gdbus.h b/src/gdbus.h new file mode 100644 index 0000000..b9c71cc --- /dev/null +++ b/src/gdbus.h @@ -0,0 +1,107 @@ +#pragma once + +#include + +/** + * virtDBusGDBusMethodFunc: + * @inArgs: input arguments of the method call + * @inFDs: list of input file descriptors + * @objectPath: the object path the method was called on + * @userData: user data passed when registering new object or subtree + * @outArgs: return location of output arguments + * @outFDs: return location of output file descriptors + * @error: return location for error + * + * Handles D-Bus method call. In case of error the handler has + * to set an @error. + */ +typedef void +(*virtDBusGDBusMethodFunc)(GVariant *inArgs, + GUnixFDList *inFDs, + const gchar *objectPath, + gpointer userData, + GVariant **outArgs, + GUnixFDList **outFDs, + GError **error); + +/** + * virtDBusGDBusPropertyGetFunc: + * @objectPath: the object path the method was called on + * @userData: user data passed when registering new object or subtree + * @value: return location for property value + * @error: return location for error + * + * Handles D-Bus Get action on a property. In case of error the handler + * has to set an @error, otherwise @value has to be set. + */ +typedef void +(*virtDBusGDBusPropertyGetFunc)(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error); + +/** + * virtDBusGDBusPropertySetFunc: + * @objectPath: the object path the method was called on + * @value: new value that should be set to the property + * @userData: user data passed when registering new object or subtree + * @error: return location for error + * + * Handles D-Bus Set action on a property. In case of error the handler + * has to set an @error. + */ +typedef void +(*virtDBusGDBusPropertySetFunc)(GVariant *value, + const gchar *objectPath, + gpointer userData, + GError **error); + +/** + * virtDBusGDBusEnumerateFunc: + * @userData: user data passed when registering new subtree + * + * Handles D-Bus introspection for subtree of objects. + * + * Returns a list of objects or NULL. + */ +typedef gchar ** +(*virtDBusGDBusEnumerateFunc)(gpointer userData); + +struct _virtDBusGDBusMethodTable { + const gchar *name; + virtDBusGDBusMethodFunc methodFunc; +}; +typedef struct _virtDBusGDBusMethodTable virtDBusGDBusMethodTable; + +struct _virtDBusGDBusPropertyTable { + const gchar *name; + virtDBusGDBusPropertyGetFunc getFunc; + virtDBusGDBusPropertySetFunc setFunc; +}; +typedef struct _virtDBusGDBusPropertyTable virtDBusGDBusPropertyTable; + +typedef guint virtDBusGDBusSource; +typedef guint virtDBusGDBusOwner; + +GDBusInterfaceInfo * +virtDBusGDBusLoadIntrospectData(gchar const *interface); + +void +virtDBusGDBusRegisterObject(GDBusConnection *bus, + gchar const *objectPath, + GDBusInterfaceInfo *interface, + virtDBusGDBusMethodTable *methods, + virtDBusGDBusPropertyTable *properties, + gpointer userData); + +void +virtDBusGDBusRegisterSubtree(GDBusConnection *bus, + gchar const *objectPath, + GDBusInterfaceInfo *interface, + virtDBusGDBusEnumerateFunc enumerate, + virtDBusGDBusMethodTable *methods, + virtDBusGDBusPropertyTable *properties, + gpointer userData); + +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/test/Makefile.am b/test/Makefile.am index 4651d08..d3997f3 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,4 +13,5 @@ EXTRA_DIST =3D \ travis-run =20 TESTS_ENVIRONMENT =3D \ - abs_top_builddir=3D$(abs_top_builddir) + abs_top_builddir=3D$(abs_top_builddir) \ + VIRT_DBUS_INTERFACES_DIR=3D$(abs_top_srcdir)/data diff --git a/test/travis-run b/test/travis-run index 482b286..28260f4 100755 --- a/test/travis-run +++ b/test/travis-run @@ -22,7 +22,7 @@ sudo chroot "$CHROOT" << EOF set -ex # install build deps apt-get update -apt-get install -y dh-autoreconf pkg-config libvirt-dev libsystemd-dev lib= tool python3-gi python3-dbus dbus +apt-get install -y dh-autoreconf pkg-config libvirt-dev libsystemd-dev lib= glib2.0-dev libtool python3-gi python3-dbus dbus =20 # run build and tests as user chown -R buildd:buildd /build --=20 2.14.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sun May 5 21:53:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1521548123136427.09549651566533; Tue, 20 Mar 2018 05:15:23 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 841843ADAA; Tue, 20 Mar 2018 12:15:21 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 500051B429; Tue, 20 Mar 2018 12:15:21 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 66290181BA04; Tue, 20 Mar 2018 12:15:20 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w2KCFHGl028437 for ; Tue, 20 Mar 2018 08:15:17 -0400 Received: by smtp.corp.redhat.com (Postfix) id 5F1972024CA6; Tue, 20 Mar 2018 12:15:17 +0000 (UTC) Received: from antique-work.brq.redhat.com (unknown [10.43.2.152]) by smtp.corp.redhat.com (Postfix) with ESMTP id BFE2B2026609 for ; Tue, 20 Mar 2018 12:15:16 +0000 (UTC) From: Pavel Hrdina To: libvir-list@redhat.com Date: Tue, 20 Mar 2018 13:15:13 +0100 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-loop: libvir-list@redhat.com Subject: [libvirt] [dbus PATCH v2 2/3] switch from sd-bus to GDBus implementation X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 20 Mar 2018 12:15:22 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" This removes all the sd-bus code and uses GDBus instead. Signed-off-by: Pavel Hrdina --- README | 1 - configure.ac | 3 - data/Makefile.am | 4 +- data/org.libvirt.Connect.xml | 56 ++++ data/org.libvirt.Domain.xml | 51 +++ libvirt-dbus.spec.in | 4 +- src/Makefile.am | 3 - src/connect.c | 316 ++++++++---------- src/connect.h | 35 +- src/domain.c | 749 ++++++++++++++++++++-------------------= ---- src/domain.h | 7 +- src/events.c | 177 +++++----- src/main.c | 300 +++++++---------- src/util.c | 170 +++++----- src/util.h | 53 ++- test/travis-run | 2 +- 16 files changed, 881 insertions(+), 1050 deletions(-) create mode 100644 data/org.libvirt.Connect.xml create mode 100644 data/org.libvirt.Domain.xml diff --git a/README b/README index a85114e..b95b09b 100644 --- a/README +++ b/README @@ -56,7 +56,6 @@ raised in future releases based on this distro build targ= et policy. =20 The packages required to build libvirt-dbus are =20 - - systemd-211 - libvirt - glib2 =20 diff --git a/configure.ac b/configure.ac index 0e3bc01..8c4e514 100644 --- a/configure.ac +++ b/configure.ac @@ -13,11 +13,9 @@ AM_SILENT_RULES([yes]) =20 GLIB2_REQUIRED=3D2.44.0 LIBVIRT_REQUIRED=3D1.2.8 -SYSTEMD_REQUIRED=3D211 LIBVIRT_GLIB_REQUIRED=3D0.0.7 AC_SUBST([GLIB2_REQUIRED]) dnl used in the .spec file AC_SUBST([LIBVIRT_REQUIRED]) dnl used in the .spec file -AC_SUBST([SYSTEMD_REQUIRED]) dnl used in the .spec file AC_SUBST([LIBVIRT_GLIB_REQUIRED]) dnl used in the .spec file =20 LIBVIRT_DBUS_MAJOR_VERSION=3D`echo $VERSION | awk -F. '{print $1}'` @@ -41,7 +39,6 @@ AC_PROG_CC_STDC PKG_CHECK_MODULES(GIO2, gio-unix-2.0 >=3D GLIB2_REQUIRED) PKG_CHECK_MODULES(GLIB2, glib-2.0 >=3D GLIB2_REQUIRED) PKG_CHECK_MODULES(LIBVIRT, libvirt >=3D $LIBVIRT_REQUIRED) -PKG_CHECK_MODULES(SYSTEMD, libsystemd >=3D $SYSTEMD_REQUIRED) PKG_CHECK_MODULES(LIBVIRT_GLIB, libvirt-glib-1.0 >=3D LIBVIRT_GLIB_REQUIRE= D) =20 LIBVIRT_COMPILE_WARNINGS diff --git a/data/Makefile.am b/data/Makefile.am index a886687..dd60713 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -18,7 +18,9 @@ polkit_files =3D \ polkitdir =3D $(sysconfdir)/polkit-1/rules.d polkit_DATA =3D $(polkit_files:.rules.in=3D.rules) =20 -interfaces_files =3D +interfaces_files =3D \ + org.libvirt.Connect.xml \ + org.libvirt.Domain.xml interfacesdir =3D $(DBUS_INTERFACES_DIR) interfaces_DATA =3D $(interfaces_files) =20 diff --git a/data/org.libvirt.Connect.xml b/data/org.libvirt.Connect.xml new file mode 100644 index 0000000..787cd8d --- /dev/null +++ b/data/org.libvirt.Connect.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/org.libvirt.Domain.xml b/data/org.libvirt.Domain.xml new file mode 100644 index 0000000..48bf40f --- /dev/null +++ b/data/org.libvirt.Domain.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libvirt-dbus.spec.in b/libvirt-dbus.spec.in index 662ece1..eb531bb 100644 --- a/libvirt-dbus.spec.in +++ b/libvirt-dbus.spec.in @@ -2,7 +2,6 @@ =20 %define glib2_version @GLIB2_REQUIRED@ %define libvirt_version @LIBVIRT_REQUIRED@ -%define systemd_version @SYSTEMD_REQUIRED@ %define libvirt_glib_version @LIBVIRT_GLIB_REQUIRED@ %define system_user @SYSTEM_USER@ =20 @@ -19,12 +18,10 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-ro= ot-%(%{__id_u} -n) BuildRequires: gcc BuildRequires: glib2-devel >=3D %{glib2_version} BuildRequires: libvirt-devel >=3D %{libvirt_version} -BuildRequires: systemd-devel >=3D %{systemd_version} BuildRequires: libvirt-glib-devel >=3D %{libvirt_glib_version} =20 Requires: glib2 >=3D %{glib2_version} Requires: libvirt-libs >=3D %{libvirt_version} -Requires: systemd-libs >=3D %{systemd_version} Requires: libvirt-glib >=3D %{libvirt_glib_version} =20 Requires(pre): shadow-utils @@ -61,5 +58,6 @@ exit 0 %{_datadir}/dbus-1/services/org.libvirt.service %{_datadir}/dbus-1/system-services/org.libvirt.service %{_datadir}/dbus-1/system.d/org.libvirt.conf +%{_datadir}/dbus-1/interfaces/org.libvirt.*.xml =20 %changelog diff --git a/src/Makefile.am b/src/Makefile.am index e7bba9d..7248561 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,6 @@ bin_PROGRAMS =3D libvirt-dbus libvirt_dbus_SOURCES =3D $(DAEMON_SOURCES) =20 libvirt_dbus_CFLAGS =3D \ - $(SYSTEMD_CFLAGS) \ $(GIO2_CFLAGS) \ $(GLIB2_CFLAGS) \ $(LIBVIRT_CFLAGS) \ @@ -29,7 +28,6 @@ libvirt_dbus_CFLAGS =3D \ $(NULL) =20 libvirt_dbus_LDFLAGS =3D \ - $(SYSTEMD_LDFLAGS) \ $(GIO2_LDFLAGS) \ $(GLIB2_LDFLAGS) \ $(LIBVIRT_LDFLAGS) \ @@ -39,7 +37,6 @@ libvirt_dbus_LDFLAGS =3D \ $(NULL) =20 libvirt_dbus_LDADD =3D \ - $(SYSTEMD_LIBS) \ $(GIO2_LIBS) \ $(GLIB2_LIBS) \ $(LIBVIRT_LIBS) \ diff --git a/src/connect.c b/src/connect.c index 695fc0d..b3ead76 100644 --- a/src/connect.c +++ b/src/connect.c @@ -1,12 +1,11 @@ +#include "connect.h" #include "domain.h" #include "events.h" -#include "connect.h" #include "util.h" =20 -#include -#include +#include =20 -static int virtDBusConnectCredType[] =3D { +static gint virtDBusConnectCredType[] =3D { VIR_CRED_AUTHNAME, VIR_CRED_ECHOPROMPT, VIR_CRED_REALM, @@ -15,31 +14,31 @@ static int virtDBusConnectCredType[] =3D { VIR_CRED_EXTERNAL, }; =20 -static int -virtDBusConnectAuthCallback(virConnectCredentialPtr cred VIRT_ATTR_UNUSED, - unsigned int ncred VIRT_ATTR_UNUSED, - void *cbdata) +static gint +virtDBusConnectAuthCallback(virConnectCredentialPtr cred G_GNUC_UNUSED, + guint ncred G_GNUC_UNUSED, + gpointer cbdata) { - sd_bus_error *error =3D cbdata; - - return virtDBusUtilSetError(error, - "Interactive authentication is not support= ed. " - "Use client configuration file for libvirt= ."); + GError **error =3D cbdata; + g_set_error(error, VIRT_DBUS_ERROR, VIRT_DBUS_ERROR_LIBVIRT, + "Interactive authentication is not supported. " + "Use client configuration file for libvirt."); + return -1; } =20 static virConnectAuth virtDBusConnectAuth =3D { virtDBusConnectCredType, - VIRT_N_ELEMENTS(virtDBusConnectCredType), + G_N_ELEMENTS(virtDBusConnectCredType), virtDBusConnectAuthCallback, NULL, }; =20 static void virtDBusConnectClose(virtDBusConnect *connect, - bool deregisterEvents) + gboolean deregisterEvents) { =20 - for (int i =3D 0; i < VIR_DOMAIN_EVENT_ID_LAST; i +=3D 1) { + for (gint i =3D 0; i < VIR_DOMAIN_EVENT_ID_LAST; i +=3D 1) { if (connect->callback_ids[i] >=3D 0) { if (deregisterEvents) { virConnectDomainEventDeregisterAny(connect->connection, @@ -53,130 +52,91 @@ virtDBusConnectClose(virtDBusConnect *connect, connect->connection =3D NULL; } =20 -int +gboolean virtDBusConnectOpen(virtDBusConnect *connect, - sd_bus_error *error) + GError **error) { if (connect->connection) { if (virConnectIsAlive(connect->connection)) - return 0; + return TRUE; else - virtDBusConnectClose(connect, false); + virtDBusConnectClose(connect, FALSE); } =20 virtDBusConnectAuth.cbdata =3D error; =20 connect->connection =3D virConnectOpenAuth(connect->uri, &virtDBusConnectAuth, 0); - if (!connect->connection) - return virtDBusUtilSetLastVirtError(error); + if (!connect->connection) { + if (error && !*error) + virtDBusUtilSetLastVirtError(error); + return FALSE; + } =20 virtDBusEventsRegister(connect); =20 - return 0; + return TRUE; } =20 -static int -virtDBusConnectEnumarateDomains(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path VIRT_ATTR_UNUSED, - void *userdata, - char ***nodes, - sd_bus_error *error) +static void +virtDBusConnectListDomains(GVariant *inArgs, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainListFreep) virDomainPtr *domains =3D NU= LL; - _cleanup_(virtDBusUtilStrvFreep) char **paths =3D NULL; - int n_domains; - int r; - - r =3D virtDBusConnectOpen(connect, error); - if (r < 0) - return r; - - n_domains =3D virConnectListAllDomains(connect->connection, &domains, = 0); - if (n_domains < 0) - return virtDBusUtilSetLastVirtError(error); - - paths =3D calloc(n_domains + 1, sizeof(char *)); - - for (int i =3D 0; i < n_domains; i +=3D 1) - paths[i] =3D virtDBusUtilBusPathForVirDomain(domains[i], - connect->domainPath); + virtDBusConnect *connect =3D userData; + g_autoptr(virDomainPtr) domains =3D NULL; + guint flags; + GVariantBuilder builder; + GVariant *gdomains; =20 - *nodes =3D paths; - paths =3D NULL; + g_variant_get(inArgs, "(u)", &flags); =20 - return 0; -} + if (!virtDBusConnectOpen(connect, error)) + return; =20 -static int -virtDBusConnectListDomains(sd_bus_message *message, - void *userdata, - sd_bus_error *error) -{ - virtDBusConnect *connect =3D userdata; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply =3D NULL; - _cleanup_(virtDBusUtilVirDomainListFreep) virDomainPtr *domains =3D NU= LL; - uint32_t flags; - int r; - - r =3D sd_bus_message_read(message, "u", &flags); - if (r < 0) - return r; - - r =3D virtDBusConnectOpen(connect, error); - if (r < 0) - return r; - - r =3D virConnectListAllDomains(connect->connection, &domains, flags); - if (r < 0) + if (virConnectListAllDomains(connect->connection, &domains, flags) < 0) return virtDBusUtilSetLastVirtError(error); =20 - r =3D sd_bus_message_new_method_return(message, &reply); - if (r < 0) - return r; - - r =3D sd_bus_message_open_container(reply, 'a', "o"); - if (r < 0) - return r; + if (!*domains) + return; =20 - for (int i =3D 0; domains[i] !=3D NULL; i +=3D 1) { - _cleanup_(virtDBusUtilFreep) char *path =3D NULL; + g_variant_builder_init(&builder, G_VARIANT_TYPE("ao")); =20 + for (gint i =3D 0; domains[i]; i++) { + g_autofree gchar *path =3D NULL; path =3D virtDBusUtilBusPathForVirDomain(domains[i], connect->domainPath); =20 - r =3D sd_bus_message_append(reply, "o", path); - if (r < 0) - return r; + g_variant_builder_add(&builder, "o", path); } =20 - r =3D sd_bus_message_close_container(reply); - if (r < 0) - return r; - - return sd_bus_send(NULL, reply, NULL); + gdomains =3D g_variant_builder_end(&builder); + *outArgs =3D g_variant_new_tuple(&gdomains, 1); } =20 -static int -virtDBusConnectCreateXML(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusConnectCreateXML(GVariant *inArgs, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - const char *xml; - uint32_t flags; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - _cleanup_(virtDBusUtilFreep) char *path =3D NULL; - int r; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + g_autofree gchar *path =3D NULL; + gchar *xml; + guint flags; =20 - r =3D sd_bus_message_read(message, "su", &xml, &flags); - if (r < 0) - return r; + g_variant_get(inArgs, "(&su)", &xml, &flags); =20 - r =3D virtDBusConnectOpen(connect, error); - if (r < 0) - return r; + if (!virtDBusConnectOpen(connect, error)) + return; =20 domain =3D virDomainCreateXML(connect->connection, xml, flags); if (!domain) @@ -184,27 +144,27 @@ virtDBusConnectCreateXML(sd_bus_message *message, =20 path =3D virtDBusUtilBusPathForVirDomain(domain, connect->domainPath); =20 - return sd_bus_reply_method_return(message, "o", path); + *outArgs =3D g_variant_new("(o)", path); } =20 -static int -virtDBusConnectDefineXML(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusConnectDefineXML(GVariant *inArgs, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - const char *xml; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - _cleanup_(virtDBusUtilFreep) char *path =3D NULL; - int r; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + g_autofree gchar *path =3D NULL; + gchar *xml; =20 - r =3D sd_bus_message_read(message, "s", &xml); - if (r < 0) - return r; + g_variant_get(inArgs, "(&s)", &xml); =20 - r =3D virtDBusConnectOpen(connect, error); - if (r < 0) - return r; + if (!virtDBusConnectOpen(connect, error)) + return; =20 domain =3D virDomainDefineXML(connect->connection, xml); if (!domain) @@ -212,97 +172,73 @@ virtDBusConnectDefineXML(sd_bus_message *message, =20 path =3D virtDBusUtilBusPathForVirDomain(domain, connect->domainPath); =20 - return sd_bus_reply_method_return(message, "o", path); + *outArgs =3D g_variant_new("(o)", path); } =20 -static const sd_bus_vtable virt_connect_vtable[] =3D { - SD_BUS_VTABLE_START(0), +static virtDBusGDBusMethodTable virtDBusConnectMethodTable[] =3D { + { "ListDomains", virtDBusConnectListDomains }, + { "CreateXML", virtDBusConnectCreateXML }, + { "DefineXML", virtDBusConnectDefineXML }, + { NULL, NULL } +}; =20 - SD_BUS_METHOD("ListDomains", "u", "ao", virtDBusConnectListDomains, SD= _BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("CreateXML", "su", "o", virtDBusConnectCreateXML, SD_BUS= _VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("DefineXML", "s", "o", virtDBusConnectDefineXML, SD_BUS_= VTABLE_UNPRIVILEGED), +static GDBusInterfaceInfo *interfaceInfo =3D NULL; =20 - SD_BUS_SIGNAL("DomainDefined", "so", 0), - SD_BUS_SIGNAL("DomainUndefined", "so", 0), - SD_BUS_SIGNAL("DomainStarted", "so", 0), - SD_BUS_SIGNAL("DomainSuspended", "so", 0), - SD_BUS_SIGNAL("DomainResumed", "so", 0), - SD_BUS_SIGNAL("DomainStopped", "so", 0), - SD_BUS_SIGNAL("DomainShutdown", "so", 0), - SD_BUS_SIGNAL("DomainPMSuspended", "so", 0), - SD_BUS_SIGNAL("DomainCrashed", "so", 0), +static void +virtDBusConnectFree(virtDBusConnect *connect) +{ + if (connect->connection) + virtDBusConnectClose(connect, TRUE); =20 - SD_BUS_VTABLE_END -}; + g_free(connect->domainPath); + g_free(connect); +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virtDBusConnect, virtDBusConnectFree); =20 -int +void virtDBusConnectNew(virtDBusConnect **connectp, - sd_bus *bus, - const char *uri, - const char *connectPath) + GDBusConnection *bus, + const gchar *uri, + const gchar *connectPath) { - _cleanup_(virtDBusConnectFreep) virtDBusConnect *connect =3D NULL; - int r; + g_autoptr(virtDBusConnect) connect =3D NULL; + + if (!interfaceInfo) { + interfaceInfo =3D virtDBusGDBusLoadIntrospectData(VIRT_DBUS_CONNEC= T_INTERFACE); + g_assert(interfaceInfo !=3D NULL); + } =20 - connect =3D calloc(1, sizeof(virtDBusConnect)); - for (int i =3D 0; i < VIR_DOMAIN_EVENT_ID_LAST; i +=3D 1) + connect =3D g_new0(virtDBusConnect, 1); + g_assert(connect !=3D NULL); + + for (gint i =3D 0; i < VIR_DOMAIN_EVENT_ID_LAST; i +=3D 1) connect->callback_ids[i] =3D -1; =20 - connect->bus =3D sd_bus_ref(bus); + connect->bus =3D bus; connect->uri =3D uri; connect->connectPath =3D connectPath; =20 - connect->enumerateDomains =3D virtDBusConnectEnumarateDomains; - - r =3D sd_bus_add_object_vtable(connect->bus, - NULL, - connect->connectPath, - VIRT_DBUS_CONNECT_INTERFACE, - virt_connect_vtable, - connect); - if (r < 0) - return r; + virtDBusGDBusRegisterObject(bus, + connect->connectPath, + interfaceInfo, + virtDBusConnectMethodTable, + NULL, + connect); =20 - if ((r =3D virtDBusDomainRegister(connect, bus) < 0)) - return r; + virtDBusDomainRegister(connect); =20 *connectp =3D connect; connect =3D NULL; - - return 0; -} - -virtDBusConnect * -virtDBusConnectFree(virtDBusConnect *connect) -{ - if (connect->bus) - sd_bus_unref(connect->bus); - - if (connect->connection) - virtDBusConnectClose(connect, true); - - free(connect->domainPath); - - free(connect); - - return NULL; -} - -void -virtDBusConnectFreep(virtDBusConnect **connectp) -{ - if (*connectp) - virtDBusConnectFree(*connectp); } =20 void -virtDBusConnectListFree(virtDBusConnect ***connectList) +virtDBusConnectListFree(virtDBusConnect **connectList) { - if (!*connectList) + if (!connectList) return; =20 - for (int i =3D 0; (*connectList)[i]; i +=3D 1) - virtDBusConnectFree((*connectList)[i]); + for (gint i =3D 0; connectList[i]; i +=3D 1) + virtDBusConnectFree(connectList[i]); =20 - free(*connectList); + g_free(connectList); } diff --git a/src/connect.h b/src/connect.h index 9e5f533..f8b1d06 100644 --- a/src/connect.h +++ b/src/connect.h @@ -2,39 +2,32 @@ =20 #define VIR_ENUM_SENTINELS =20 +#include "util.h" + #include -#include =20 #define VIRT_DBUS_CONNECT_INTERFACE "org.libvirt.Connect" =20 struct virtDBusConnect { - sd_bus *bus; - const char *uri; - const char *connectPath; - char *domainPath; + GDBusConnection *bus; + const gchar *uri; + const gchar *connectPath; + gchar *domainPath; virConnectPtr connection; =20 - sd_bus_node_enumerator_t enumerateDomains; - - int callback_ids[VIR_DOMAIN_EVENT_ID_LAST]; + gint callback_ids[VIR_DOMAIN_EVENT_ID_LAST]; }; typedef struct virtDBusConnect virtDBusConnect; =20 -int +void virtDBusConnectNew(virtDBusConnect **connectp, - sd_bus *bus, - const char *uri, - const char *connectPath); + GDBusConnection *bus, + const gchar *uri, + const gchar *connectPath); =20 -int +gboolean virtDBusConnectOpen(virtDBusConnect *connect, - sd_bus_error *error); - -virtDBusConnect * -virtDBusConnectFree(virtDBusConnect *connect); - -void -virtDBusConnectFreep(virtDBusConnect **connectp); + GError **error); =20 void -virtDBusConnectListFree(virtDBusConnect ***connectList); +virtDBusConnectListFree(virtDBusConnect **connectList); diff --git a/src/domain.c b/src/domain.c index f68a3a0..fb53c5b 100644 --- a/src/domain.c +++ b/src/domain.c @@ -1,208 +1,192 @@ -#define _GNU_SOURCE - #include "domain.h" #include "util.h" =20 #include -#include =20 static virDomainPtr virtDBusDomainGetVirDomain(virtDBusConnect *connect, - const char *path, - sd_bus_error *error) + const gchar *objectPath, + GError **error) { virDomainPtr domain; =20 if (virtDBusConnectOpen(connect, error) < 0) return NULL; =20 - domain =3D virtDBusUtilVirDomainFromBusPath(connect->connection, path, + domain =3D virtDBusUtilVirDomainFromBusPath(connect->connection, + objectPath, connect->domainPath); - if (domain =3D=3D NULL) { - sd_bus_error_setf(error, - SD_BUS_ERROR_UNKNOWN_OBJECT, - "Unknown object '%s'.", path); + if (!domain) { + virtDBusUtilSetLastVirtError(error); return NULL; } =20 return domain; } =20 -static int -virtDBusDomainGetName(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetName(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - const char *name =3D ""; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + const gchar *name; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 name =3D virDomainGetName(domain); - if (name =3D=3D NULL) - return sd_bus_message_append(reply, "s", ""); + if (!name) + return virtDBusUtilSetLastVirtError(error); =20 - return sd_bus_message_append(reply, "s", name); + *value =3D g_variant_new("s", name); } =20 -static int -virtDBusDomainGetUUID(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetUUID(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - char uuid[VIR_UUID_STRING_BUFLEN] =3D ""; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + gchar uuid[VIR_UUID_STRING_BUFLEN] =3D ""; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 - virDomainGetUUIDString(domain, uuid); + if (virDomainGetUUIDString(domain, uuid) < 0) + return virtDBusUtilSetLastVirtError(error); =20 - return sd_bus_message_append(reply, "s", uuid); + *value =3D g_variant_new("s", uuid); } =20 -static int -virtDBusDomainGetId(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetId(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + guint id; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; + + id =3D virDomainGetID(domain); + if (id =3D=3D (guint)-1) + return virtDBusUtilSetLastVirtError(error); =20 - return sd_bus_message_append(reply, "u", virDomainGetID(domain)); + *value =3D g_variant_new("u", id); } =20 -static int -virtDBusDomainGetVcpus(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetVcpus(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + gint vcpus; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 - return sd_bus_message_append(reply, "u", virDomainGetVcpusFlags(domain= , VIR_DOMAIN_VCPU_CURRENT)); + vcpus =3D virDomainGetVcpusFlags(domain, VIR_DOMAIN_VCPU_CURRENT); + if (vcpus < 0) + return virtDBusUtilSetLastVirtError(error); + + *value =3D g_variant_new("u", vcpus); } =20 -static int -virtDBusDomainGetOsType(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetOsType(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - _cleanup_(virtDBusUtilFreep) char *os_type =3D NULL; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + g_autofree gchar *osType =3D NULL; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 - os_type =3D virDomainGetOSType(domain); - if (os_type =3D=3D NULL) - return sd_bus_message_append(reply, "s", ""); + osType =3D virDomainGetOSType(domain); + if (!osType) + return virtDBusUtilSetLastVirtError(error); =20 - return sd_bus_message_append(reply, "s", os_type); + *value =3D g_variant_new("s", osType); } =20 -static int -virtDBusDomainGetActive(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetActive(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int active; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + gint active; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 active =3D virDomainIsActive(domain); if (active < 0) - return sd_bus_message_append(reply, "b", 0); + return virtDBusUtilSetLastVirtError(error); =20 - return sd_bus_message_append(reply, "b", active); + *value =3D g_variant_new("b", !!active); } =20 -static int -virtDBusDomainGetPersistent(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetPersistent(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int persistent; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + gint persistent; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 persistent =3D virDomainIsPersistent(domain); if (persistent < 0) - return sd_bus_message_append(reply, "b", 0); + return virtDBusUtilSetLastVirtError(error); =20 - return sd_bus_message_append(reply, "b", persistent); + *value =3D g_variant_new("b", !!persistent); } =20 -static int -virtDBusDomainGetState(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetState(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int state =3D 0; - const char *string; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + gint state =3D 0; + const gchar *string; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 - virDomainGetState(domain, &state, NULL, 0); + if (virDomainGetState(domain, &state, NULL, 0) < 0) + return virtDBusUtilSetLastVirtError(error); =20 switch (state) { case VIR_DOMAIN_NOSTATE: @@ -232,88 +216,80 @@ virtDBusDomainGetState(sd_bus *bus VIRT_ATTR_UNUSED, break; } =20 - return sd_bus_message_append(reply, "s", string); + *value =3D g_variant_new("s", string); } =20 -static int -virtDBusDomainGetAutostart(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - const char *property VIRT_ATTR_UNUSED, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error VIRT_ATTR_UNUSED) +static void +virtDBusDomainGetAutostart(const gchar *objectPath, + gpointer userData, + GVariant **value, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int autostart =3D 0; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + gint autostart =3D 0; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 - virDomainGetAutostart(domain, &autostart); + if (virDomainGetAutostart(domain, &autostart) < 0) + return virtDBusUtilSetLastVirtError(error); =20 - return sd_bus_message_append(reply, "b", autostart); + *value =3D g_variant_new("b", !!autostart); } =20 -static int -virtDBusDomainGetXMLDesc(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusDomainGetXMLDesc(GVariant *inArgs, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath, + gpointer userData, + GVariant **outArgs, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - _cleanup_(virtDBusUtilFreep) char *description =3D NULL; - uint32_t flags; - int r; - - r =3D sd_bus_message_read(message, "u", &flags); - if (r < 0) - return r; - - domain =3D virtDBusDomainGetVirDomain(connect, - sd_bus_message_get_path(message), - error); - if (domain =3D=3D NULL) - return -1; - - description =3D virDomainGetXMLDesc(domain, flags); - if (!description) + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + g_autofree gchar *xml =3D NULL; + guint flags; + + g_variant_get(inArgs, "(u)", &flags); + + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; + + xml =3D virDomainGetXMLDesc(domain, flags); + if (!xml) return virtDBusUtilSetLastVirtError(error); =20 - return sd_bus_reply_method_return(message, "s", description); + *outArgs =3D g_variant_new("(s)", xml); } =20 -static void -virtDBusDomainStatsRecordListFreep(virDomainStatsRecordPtr **statsp) -{ - if (*statsp) - virDomainStatsRecordListFree(*statsp); -} +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainStatsRecordPtr, virDomainStatsRecor= dListFree); =20 -static int -virtDBusDomainGetStats(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusDomainGetStats(GVariant *inArgs, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; virDomainPtr domains[2]; - _cleanup_(virtDBusDomainStatsRecordListFreep) virDomainStatsRecordPtr = *records =3D NULL; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply =3D NULL; - uint32_t flags, stats; - int r; + g_autoptr(virDomainStatsRecordPtr) records =3D NULL; + guint stats; + guint flags; + GVariant *grecords; =20 - r =3D sd_bus_message_read(message, "uu", &stats, &flags); - if (r < 0) - return r; + g_variant_get(inArgs, "(uu)", &stats, &flags); =20 - domain =3D virtDBusDomainGetVirDomain(connect, - sd_bus_message_get_path(message), - error); - if (domain =3D=3D NULL) - return -1; + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 domains[0] =3D domain; domains[1] =3D NULL; @@ -321,243 +297,212 @@ virtDBusDomainGetStats(sd_bus_message *message, if (virDomainListGetStats(domains, stats, &records, flags) !=3D 1) return virtDBusUtilSetLastVirtError(error); =20 - r =3D sd_bus_message_new_method_return(message, &reply); - if (r < 0) - return r; - - r =3D virtDBusUtilMessageAppendTypedParameters(reply, records[0]->para= ms, records[0]->nparams); - if (r < 0) - return r; + grecords =3D virtDBusUtilTypedParamsToGVariant(records[0]->params, + records[0]->nparams); =20 - return sd_bus_send(NULL, reply, NULL); + *outArgs =3D g_variant_new_tuple(&grecords, 1); } =20 -static int -virtDBusDomainShutdown(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusDomainShutdown(GVariant *inArgs G_GNUC_UNUSED, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs G_GNUC_UNUSED, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int r; - - domain =3D virtDBusDomainGetVirDomain(connect, - sd_bus_message_get_path(message), - error); - if (domain =3D=3D NULL) - return -1; - - r =3D virDomainShutdown(domain); - if (r < 0) - return virtDBusUtilSetLastVirtError(error); + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; =20 - return sd_bus_reply_method_return(message, ""); + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; + + if (virDomainShutdown(domain) < 0) + virtDBusUtilSetLastVirtError(error); } =20 -static int -virtDBusDomainDestroy(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusDomainDestroy(GVariant *inArgs G_GNUC_UNUSED, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs G_GNUC_UNUSED, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int r; - - domain =3D virtDBusDomainGetVirDomain(connect, - sd_bus_message_get_path(message), - error); - if (domain =3D=3D NULL) - return -1; - - r =3D virDomainDestroy(domain); - if (r < 0) - return virtDBusUtilSetLastVirtError(error); + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 - return sd_bus_reply_method_return(message, ""); + if (virDomainDestroy(domain) < 0) + virtDBusUtilSetLastVirtError(error); } =20 -static int -virtDBusDomainReboot(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusDomainReboot(GVariant *inArgs, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs G_GNUC_UNUSED, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) + { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - uint32_t flags; - int r; - - r =3D sd_bus_message_read(message, "u", &flags); - if (r < 0) - return r; - - domain =3D virtDBusDomainGetVirDomain(connect, - sd_bus_message_get_path(message), - error); - if (domain =3D=3D NULL) - return -1; - - r =3D virDomainReboot(domain, flags); - if (r < 0) - return virtDBusUtilSetLastVirtError(error); + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + guint flags; + + g_variant_get(inArgs, "(u)", &flags); =20 - return sd_bus_reply_method_return(message, ""); + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; + + if (virDomainReboot(domain, flags) < 0) + virtDBusUtilSetLastVirtError(error); } =20 -static int -virtDBusDomainReset(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusDomainReset(GVariant *inArgs, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs G_GNUC_UNUSED, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) + { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - uint32_t flags; - int r; - - r =3D sd_bus_message_read(message, "u", &flags); - if (r < 0) - return r; - - domain =3D virtDBusDomainGetVirDomain(connect, - sd_bus_message_get_path(message), - error); - if (domain =3D=3D NULL) - return -1; - - r =3D virDomainReset(domain, flags); - if (r < 0) - return virtDBusUtilSetLastVirtError(error); + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + guint flags; + + g_variant_get(inArgs, "(u)", &flags); + + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 - return sd_bus_reply_method_return(message, ""); + if (virDomainReset(domain, flags) < 0) + virtDBusUtilSetLastVirtError(error); } =20 -static int -virtDBusDomainCreate(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusDomainCreate(GVariant *inArgs G_GNUC_UNUSED, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs G_GNUC_UNUSED, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int r; - - domain =3D virtDBusDomainGetVirDomain(connect, - sd_bus_message_get_path(message), - error); - if (domain =3D=3D NULL) - return -1; - - r =3D virDomainCreate(domain); - if (r < 0) - return virtDBusUtilSetLastVirtError(error); + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; =20 - return sd_bus_reply_method_return(message, ""); + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; + + if (virDomainCreate(domain) < 0) + virtDBusUtilSetLastVirtError(error); } =20 -static int -virtDBusDomainUndefine(sd_bus_message *message, - void *userdata, - sd_bus_error *error) +static void +virtDBusDomainUndefine(GVariant *inArgs G_GNUC_UNUSED, + GUnixFDList *inFDs G_GNUC_UNUSED, + const gchar *objectPath G_GNUC_UNUSED, + gpointer userData, + GVariant **outArgs G_GNUC_UNUSED, + GUnixFDList **outFDs G_GNUC_UNUSED, + GError **error) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int r; - - domain =3D virtDBusDomainGetVirDomain(connect, - sd_bus_message_get_path(message), - error); - if (domain =3D=3D NULL) - return -1; - - r =3D virDomainUndefine(domain); - if (r < 0) - return virtDBusUtilSetLastVirtError(error); + virtDBusConnect *connect =3D userData; + g_autoptr(virDomain) domain =3D NULL; + + domain =3D virtDBusDomainGetVirDomain(connect, objectPath, error); + if (!domain) + return; =20 - return sd_bus_reply_method_return(message, ""); + if (virDomainUndefine(domain) < 0) + virtDBusUtilSetLastVirtError(error); } =20 -static const sd_bus_vtable virt_domain_vtable[] =3D { - SD_BUS_VTABLE_START(0), - - SD_BUS_PROPERTY("Name", "s", virtDBusDomainGetName, 0, 0), - SD_BUS_PROPERTY("UUID", "s", virtDBusDomainGetUUID, 0, 0), - SD_BUS_PROPERTY("Id", "u", virtDBusDomainGetId, 0, 0), - SD_BUS_PROPERTY("Vcpus", "u", virtDBusDomainGetVcpus, 0, 0), - SD_BUS_PROPERTY("OSType", "s", virtDBusDomainGetOsType, 0, 0), - SD_BUS_PROPERTY("Active", "b", virtDBusDomainGetActive, 0, 0), - SD_BUS_PROPERTY("Persistent", "b", virtDBusDomainGetPersistent, 0, 0), - SD_BUS_PROPERTY("State", "s", virtDBusDomainGetState, 0, 0), - SD_BUS_PROPERTY("Autostart", "b", virtDBusDomainGetAutostart, 0, 0), - - SD_BUS_METHOD("GetXMLDesc", "u", "s", virtDBusDomainGetXMLDesc, SD_BUS= _VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("GetStats", "uu", "a{sv}", virtDBusDomainGetStats, SD_BU= S_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("Shutdown", "", "", virtDBusDomainShutdown, SD_BUS_VTABL= E_UNPRIVILEGED), - SD_BUS_METHOD("Destroy", "", "", virtDBusDomainDestroy, SD_BUS_VTABLE_= UNPRIVILEGED), - SD_BUS_METHOD("Reboot", "u", "", virtDBusDomainReboot, SD_BUS_VTABLE_U= NPRIVILEGED), - SD_BUS_METHOD("Reset", "u", "", virtDBusDomainReset, SD_BUS_VTABLE_UNP= RIVILEGED), - SD_BUS_METHOD("Create", "", "", virtDBusDomainCreate, SD_BUS_VTABLE_UN= PRIVILEGED), - SD_BUS_METHOD("Undefine", "", "", virtDBusDomainUndefine, SD_BUS_VTABL= E_UNPRIVILEGED), - - SD_BUS_SIGNAL("DeviceAdded", "s", 0), - SD_BUS_SIGNAL("DeviceRemoved", "s", 0), - SD_BUS_SIGNAL("DiskChange", "ssss", 0), - SD_BUS_SIGNAL("TrayChange", "ss", 0), - - SD_BUS_VTABLE_END +static virtDBusGDBusPropertyTable virtDBusDomainPropertyTable[] =3D { + { "Name", virtDBusDomainGetName, NULL }, + { "UUID", virtDBusDomainGetUUID, NULL }, + { "Id", virtDBusDomainGetId, NULL }, + { "Vcpus", virtDBusDomainGetVcpus, NULL }, + { "OSType", virtDBusDomainGetOsType, NULL }, + { "Active", virtDBusDomainGetActive, NULL }, + { "Persistent", virtDBusDomainGetPersistent, NULL }, + { "State", virtDBusDomainGetState, NULL }, + { "Autostart", virtDBusDomainGetAutostart, NULL }, + { NULL, NULL, NULL } +}; + +static virtDBusGDBusMethodTable virtDBusDomainMethodTable[] =3D { + { "GetXMLDesc", virtDBusDomainGetXMLDesc }, + { "GetStats", virtDBusDomainGetStats }, + { "Shutdown", virtDBusDomainShutdown }, + { "Destroy", virtDBusDomainDestroy }, + { "Reboot", virtDBusDomainReboot }, + { "Reset", virtDBusDomainReset }, + { "Create", virtDBusDomainCreate }, + { "Undefine", virtDBusDomainUndefine }, + { NULL, NULL } }; =20 -static int -virtDBusDomainLookup(sd_bus *bus VIRT_ATTR_UNUSED, - const char *path, - const char *interface VIRT_ATTR_UNUSED, - void *userdata, - void **found, - sd_bus_error *error VIRT_ATTR_UNUSED) +static gchar ** +virtDBusDomainEnumerate(gpointer userData) { - virtDBusConnect *connect =3D userdata; - _cleanup_(virtDBusUtilFreep) char *name =3D NULL; - _cleanup_(virtDBusUtilVirDomainFreep) virDomainPtr domain =3D NULL; - int r; + virtDBusConnect *connect =3D userData; + g_autoptr(virDomainPtr) domains =3D NULL; + gint num =3D 0; + gchar **ret =3D NULL; =20 - r =3D sd_bus_path_decode(path, connect->domainPath, &name); - if (r < 0) - return r; + if (!virtDBusConnectOpen(connect, NULL)) + return NULL; =20 - if (*name =3D=3D '\0') - return 0; + num =3D virConnectListAllDomains(connect->connection, &domains, 0); + if (num < 0) + return NULL; =20 - domain =3D virtDBusDomainGetVirDomain(connect, path, error); - if (!domain) - return 0; + if (num =3D=3D 0) + return NULL; + + ret =3D g_new0(gchar *, num + 1); + g_assert(ret); =20 - /* - * There's no way to unref the pointer we're returning here. So, - * return the connect object and look up the domain again in the - * domain_* callbacks. - */ - *found =3D connect; + for (gint i =3D 0; i < num; i++) { + ret[i] =3D virtDBusUtilBusPathForVirDomain(domains[i], + connect->domainPath); + } =20 - return 1; + return ret; } =20 -int -virtDBusDomainRegister(virtDBusConnect *connect, - sd_bus *bus) +static GDBusInterfaceInfo *interfaceInfo =3D NULL; + +void +virtDBusDomainRegister(virtDBusConnect *connect) { - int r; - - r =3D asprintf(&connect->domainPath, "%s/domain", connect->connectPath= ); - if (r < 0) - return r; - - r =3D sd_bus_add_node_enumerator(bus, NULL, connect->domainPath, - connect->enumerateDomains, connect); - if (r < 0) - return r; - - return sd_bus_add_fallback_vtable(bus, - NULL, - connect->domainPath, - VIRT_DBUS_DOMAIN_INTERFACE, - virt_domain_vtable, - virtDBusDomainLookup, - connect); + connect->domainPath =3D g_strdup_printf("%s/domain", connect->connectP= ath); + g_assert(connect->domainPath); + + if (!interfaceInfo) { + interfaceInfo =3D virtDBusGDBusLoadIntrospectData(VIRT_DBUS_DOMAIN= _INTERFACE); + g_assert(interfaceInfo !=3D NULL); + } + + virtDBusGDBusRegisterSubtree(connect->bus, + connect->domainPath, + interfaceInfo, + virtDBusDomainEnumerate, + virtDBusDomainMethodTable, + virtDBusDomainPropertyTable, + connect); } diff --git a/src/domain.h b/src/domain.h index 03a29ed..d56d703 100644 --- a/src/domain.h +++ b/src/domain.h @@ -2,10 +2,7 @@ =20 #include "connect.h" =20 -#include - #define VIRT_DBUS_DOMAIN_INTERFACE "org.libvirt.Domain" =20 -int -virtDBusDomainRegister(virtDBusConnect *connect, - sd_bus *bus); +void +virtDBusDomainRegister(virtDBusConnect *connect); diff --git a/src/events.c b/src/events.c index c45acd7..dada55f 100644 --- a/src/events.c +++ b/src/events.c @@ -2,23 +2,19 @@ #include "events.h" #include "util.h" =20 -#include #include -#include =20 -static int -virtDBusEventsDomainLifecycle(virConnectPtr connection VIRT_ATTR_UNUSED, +static gint +virtDBusEventsDomainLifecycle(virConnectPtr connection G_GNUC_UNUSED, virDomainPtr domain, - int event, - int detail VIRT_ATTR_UNUSED, - void *opaque) + gint event, + gint detail G_GNUC_UNUSED, + gpointer opaque) { virtDBusConnect *connect =3D opaque; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *message =3D NULL; - const char *signal =3D NULL; - const char *name; - _cleanup_(virtDBusUtilFreep) char *path =3D NULL; - int r; + const gchar *signal =3D NULL; + const gchar *name; + g_autofree gchar *path =3D NULL; =20 switch (event) { case VIR_DOMAIN_EVENT_DEFINED: @@ -52,103 +48,77 @@ virtDBusEventsDomainLifecycle(virConnectPtr connection= VIRT_ATTR_UNUSED, return 0; } =20 - r =3D sd_bus_message_new_signal(connect->bus, - &message, - connect->connectPath, - VIRT_DBUS_CONNECT_INTERFACE, - signal); - if (r < 0) - return r; - name =3D virDomainGetName(domain); path =3D virtDBusUtilBusPathForVirDomain(domain, connect->domainPath); =20 - r =3D sd_bus_message_append(message, "so", name ? : "", path); - if (r < 0) - return r; + g_dbus_connection_emit_signal(connect->bus, + NULL, + connect->connectPath, + VIRT_DBUS_CONNECT_INTERFACE, + signal, + g_variant_new("(so)", name, path), + NULL); =20 - return sd_bus_send(connect->bus, message, NULL); + return 0; } =20 -static int -virtDBusEventsDomainDeviceAdded(virConnectPtr connection VIRT_ATTR_UNUSED, +static gint +virtDBusEventsDomainDeviceAdded(virConnectPtr connection G_GNUC_UNUSED, virDomainPtr domain, - const char *device, - void *opaque) + const gchar *device, + gpointer opaque) { virtDBusConnect *connect =3D opaque; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *message =3D NULL; - _cleanup_(virtDBusUtilFreep) char *path =3D NULL; - int r; + g_autofree gchar *path =3D NULL; =20 path =3D virtDBusUtilBusPathForVirDomain(domain, connect->domainPath); =20 - r =3D sd_bus_message_new_signal(connect->bus, - &message, + g_dbus_connection_emit_signal(connect->bus, + NULL, path, VIRT_DBUS_DOMAIN_INTERFACE, - "DeviceAdded"); - if (r < 0) - return r; + "DeviceAdded", + g_variant_new("(s)", device), + NULL); =20 - r =3D sd_bus_message_append(message, "s", device); - if (r < 0) - return r; - - return sd_bus_send(connect->bus, message, NULL); + return 0; } =20 -static int -virtDBusEventsDomainDeviceRemoved(virConnectPtr connection VIRT_ATTR_UNUSE= D, +static gint +virtDBusEventsDomainDeviceRemoved(virConnectPtr connection G_GNUC_UNUSED, virDomainPtr domain, - const char *device, - void *opaque) + const gchar *device, + gpointer opaque) { virtDBusConnect *connect =3D opaque; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *message =3D NULL; - _cleanup_(virtDBusUtilFreep) char *path =3D NULL; - int r; + g_autofree gchar *path =3D NULL; =20 path =3D virtDBusUtilBusPathForVirDomain(domain, connect->domainPath); =20 - r =3D sd_bus_message_new_signal(connect->bus, - &message, + g_dbus_connection_emit_signal(connect->bus, + NULL, path, VIRT_DBUS_DOMAIN_INTERFACE, - "DeviceRemoved"); - if (r < 0) - return r; - - r =3D sd_bus_message_append(message, "s", device); - if (r < 0) - return r; + "DeviceRemoved", + g_variant_new("(s)", device), + NULL); =20 - return sd_bus_send(connect->bus, message, NULL); + return 0; } =20 -static int -virtDBusEventsDomainTrayChange(virConnectPtr connection VIRT_ATTR_UNUSED, +static gint +virtDBusEventsDomainTrayChange(virConnectPtr connection G_GNUC_UNUSED, virDomainPtr domain, - const char *device, - int reason, - void *opaque) + const gchar *device, + gint reason, + gpointer opaque) { virtDBusConnect *connect =3D opaque; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *message =3D NULL; - _cleanup_(virtDBusUtilFreep) char *path =3D NULL; - const char *reasonstr; - int r; + g_autofree gchar *path =3D NULL; + const gchar *reasonstr; =20 path =3D virtDBusUtilBusPathForVirDomain(domain, connect->domainPath); =20 - r =3D sd_bus_message_new_signal(connect->bus, - &message, - path, - VIRT_DBUS_DOMAIN_INTERFACE, - "TrayChange"); - if (r < 0) - return r; - switch (reason) { case VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN: reasonstr =3D "open"; @@ -161,38 +131,32 @@ virtDBusEventsDomainTrayChange(virConnectPtr connecti= on VIRT_ATTR_UNUSED, break; } =20 - r =3D sd_bus_message_append(message, "ss", device, reasonstr); - if (r < 0) - return r; + g_dbus_connection_emit_signal(connect->bus, + NULL, + path, + VIRT_DBUS_DOMAIN_INTERFACE, + "TrayChange", + g_variant_new("(ss)", device, reasonstr), + NULL); =20 - return sd_bus_send(connect->bus, message, NULL); + return 0; } =20 -static int -virtDBusEventsDomainDiskChange(virConnectPtr connection VIRT_ATTR_UNUSED, +static gint +virtDBusEventsDomainDiskChange(virConnectPtr connection G_GNUC_UNUSED, virDomainPtr domain, - const char *old_src_path, - const char *new_src_path, - const char *device, - int reason, - void *opaque) + const gchar *old_src_path, + const gchar *new_src_path, + const gchar *device, + gint reason, + gpointer opaque) { virtDBusConnect *connect =3D opaque; - _cleanup_(sd_bus_message_unrefp) sd_bus_message *message =3D NULL; - _cleanup_(virtDBusUtilFreep) char *path =3D NULL; - const char *reasonstr; - int r; + g_autofree gchar *path =3D NULL; + const gchar *reasonstr; =20 path =3D virtDBusUtilBusPathForVirDomain(domain, connect->domainPath); =20 - r =3D sd_bus_message_new_signal(connect->bus, - &message, - path, - VIRT_DBUS_DOMAIN_INTERFACE, - "DiskChange"); - if (r < 0) - return r; - switch (reason) { case VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START: reasonstr =3D "missing-on-start"; @@ -205,19 +169,24 @@ virtDBusEventsDomainDiskChange(virConnectPtr connecti= on VIRT_ATTR_UNUSED, break; } =20 - r =3D sd_bus_message_append(message, "ssss", old_src_path, new_src_pat= h, device, reasonstr); - if (r < 0) - return r; + g_dbus_connection_emit_signal(connect->bus, + NULL, + path, + VIRT_DBUS_DOMAIN_INTERFACE, + "DiskChange", + g_variant_new("(ssss)", old_src_path, + new_src_path, device, reas= onstr), + NULL); =20 - return sd_bus_send(connect->bus, message, NULL); + return 0; } =20 static void virtDBusEventsRegisterEvent(virtDBusConnect *connect, - int id, + gint id, virConnectDomainEventGenericCallback callback) { - assert(connect->callback_ids[id] =3D=3D -1); + g_assert(connect->callback_ids[id] =3D=3D -1); =20 connect->callback_ids[id] =3D virConnectDomainEventRegisterAny(connect= ->connection, NULL, diff --git a/src/main.c b/src/main.c index 6f11aab..72a7e21 100644 --- a/src/main.c +++ b/src/main.c @@ -1,92 +1,23 @@ -#include "config.h" - #include "connect.h" #include "util.h" =20 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int loop_status; - -static int -virtDBusGetLibvirtEvents(sd_bus *bus) -{ - int events; - int virt_events =3D 0; - - events =3D sd_bus_get_events(bus); - - if (events & POLLIN) - virt_events |=3D VIR_EVENT_HANDLE_READABLE; - - if (events & POLLOUT) - virt_events |=3D VIR_EVENT_HANDLE_WRITABLE; - - return virt_events; -} - -static int -virtDBusProcessEvents(sd_bus *bus) -{ - for (;;) { - int r; - - r =3D sd_bus_process(bus, NULL); - if (r < 0) - return r; - - if (r =3D=3D 0) - break; - } - - return 0; -} - -static void -virtDBusVirEventRemoveHandlep(int *watchp) -{ - if (*watchp >=3D 0) - virEventRemoveHandle(*watchp); -} - -static void -virtDBusHandleSignal(int watch VIRT_ATTR_UNUSED, - int fd VIRT_ATTR_UNUSED, - int events VIRT_ATTR_UNUSED, - void *opaque VIRT_ATTR_UNUSED) -{ - loop_status =3D -ECANCELED; -} - -static void -virtDBusHandleBusEvent(int watch, - int fd VIRT_ATTR_UNUSED, - int events VIRT_ATTR_UNUSED, - void *opaque) -{ - sd_bus *bus =3D opaque; - - loop_status =3D virtDBusProcessEvents(bus); +#include +#include =20 - if (loop_status < 0) - return; - - virEventUpdateHandle(watch, virtDBusGetLibvirtEvents(bus)); -} +struct _virtDBusDriver { + const gchar *uri; + const gchar *object; +}; +typedef struct _virtDBusDriver virtDBusDriver; =20 -struct virtDBusDriver { - const char *uri; - const char *object; +struct _virtDBusRegisterData { + virtDBusConnect **connectList; + const virtDBusDriver *drivers; + gsize ndrivers; }; +typedef struct _virtDBusRegisterData virtDBusRegisterData; =20 -static const struct virtDBusDriver sessionDrivers[] =3D { +static const virtDBusDriver sessionDrivers[] =3D { { "qemu:///session", "/org/libvirt/QEMU" }, { "test:///default", "/org/libvirt/Test" }, { "uml:///session", "/org/libvirt/UML" }, @@ -96,7 +27,7 @@ static const struct virtDBusDriver sessionDrivers[] =3D { { "vmwarews:///session", "/org/libvirt/VMwareWS" }, }; =20 -static const struct virtDBusDriver systemDrivers[] =3D { +static const virtDBusDriver systemDrivers[] =3D { { "bhyve:///system", "/org/libvirt/BHyve" }, { "lxc:///", "/org/libvirt/LXC" }, { "openvz:///system", "/org/libvirt/OpenVZ" }, @@ -108,131 +39,128 @@ static const struct virtDBusDriver systemDrivers[] = =3D { { "xen:///", "/org/libvirt/Xen" }, }; =20 -int -main(int argc, char *argv[]) +static gboolean +virtDBusHandleSignal(gpointer data) { - enum { - ARG_SYSTEM =3D 255, - ARG_SESSION - }; + g_main_loop_quit(data); + return TRUE; +} =20 - static const struct option options[] =3D { - { "help", no_argument, NULL, 'h' }, - { "system", no_argument, NULL, ARG_SYSTEM }, - { "session", no_argument, NULL, ARG_SESSION }, - {} - }; +static void +virtDBusAcquired(GDBusConnection *connection, + const gchar *name G_GNUC_UNUSED, + gpointer opaque) +{ + virtDBusRegisterData *data =3D opaque; =20 - bool system_bus; - const struct virtDBusDriver *drivers =3D NULL; - int ndrivers =3D 0; - - _cleanup_(virtDBusConnectListFree) virtDBusConnect **connect =3D NULL; - _cleanup_(sd_bus_unrefp) sd_bus *bus =3D NULL; - _cleanup_(virtDBusUtilClosep) int signal_fd =3D -1; - _cleanup_(virtDBusVirEventRemoveHandlep) int bus_watch =3D -1; - _cleanup_(virtDBusVirEventRemoveHandlep) int signal_watch =3D -1; - sigset_t mask; - int c; - int r; - - if (geteuid() =3D=3D 0) { - system_bus =3D true; - } else { - system_bus =3D false; + for (gsize i =3D 0; i < data->ndrivers; i +=3D 1) { + virtDBusConnectNew(&data->connectList[i], connection, + data->drivers[i].uri, data->drivers[i].object); } =20 - while ((c =3D getopt_long(argc, argv, "hc:", options, NULL)) >=3D 0) { - switch (c) { - case 'h': - printf("Usage: %s [OPTIONS]\n", program_invocation_short_n= ame); - printf("\n"); - printf("Provide a D-Bus interface to a libvirtd.\n"); - printf("\n"); - printf(" -h, --help Display this help text and exi= t\n"); - printf(" --session Connect to the session bus\n"); - printf(" --system Connect to the system bus\n"); - return 0; - - case ARG_SYSTEM: - system_bus =3D true; - break; - - case ARG_SESSION: - system_bus =3D false; - break; - - default: - return EXIT_FAILURE; - } - } +} =20 - sigemptyset(&mask); - sigaddset(&mask, SIGTERM); - sigaddset(&mask, SIGINT); - sigprocmask(SIG_BLOCK, &mask, NULL); +static void +virtDBusNameAcquired(GDBusConnection *connection G_GNUC_UNUSED, + const gchar *name G_GNUC_UNUSED, + gpointer data G_GNUC_UNUSED) +{ +} =20 - virEventRegisterDefaultImpl(); +static void +virtDBusNameLost(GDBusConnection *connection G_GNUC_UNUSED, + const gchar *name G_GNUC_UNUSED, + gpointer data G_GNUC_UNUSED) +{ + g_printerr("Disconnected from D-Bus.\n"); + exit(EXIT_FAILURE); +} =20 - r =3D system_bus ? sd_bus_open_system(&bus) : sd_bus_open_user(&bus); - if (r < 0) { - fprintf(stderr, "Failed to connect to session bus: %s\n", strerror= (-r)); - return EXIT_FAILURE; +static void +virtDBusRegisterDataFree(virtDBusRegisterData *data) +{ + virtDBusConnectListFree(data->connectList); +} +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(virtDBusRegisterData, virtDBusRegisterDat= aFree); + +int +main(gint argc, gchar *argv[]) +{ + static gboolean systemOpt =3D FALSE; + static gboolean sessionOpt =3D FALSE; + GBusType busType; + g_auto(virtDBusGDBusSource) sigintSource =3D 0; + g_auto(virtDBusGDBusSource) sigtermSource =3D 0; + g_auto(virtDBusGDBusOwner) busOwner =3D 0; + g_autoptr(GOptionContext) context =3D NULL; + g_autoptr(GError) error =3D NULL; + g_autoptr(GMainLoop) loop =3D NULL; + g_auto(virtDBusRegisterData) data =3D { 0 }; + + static GOptionEntry options[] =3D { + { "system", 0, 0, G_OPTION_ARG_NONE, &systemOpt, + "Connect to the system bus", NULL }, + { "session", 0, 0, G_OPTION_ARG_NONE, &sessionOpt, + "Connect to the session bus", NULL }, + { NULL } + }; + + context =3D g_option_context_new("Provide a D-Bus interface to a libvi= rtd."); + g_option_context_add_main_entries(context, options, NULL); + + if (!g_option_context_parse(context, &argc, &argv, &error)) { + g_printerr("%s\n", error->message); + exit(EXIT_FAILURE); } =20 - r =3D sd_bus_request_name(bus, "org.libvirt", 0); - if (r < 0) { - fprintf(stderr, "Failed to acquire service name: %s\n", strerror(-= r)); - return EXIT_FAILURE; + if (sessionOpt && systemOpt) { + g_printerr("Only one of --session or --system can be used.\n"); + exit(EXIT_FAILURE); } =20 - if (system_bus) { - drivers =3D systemDrivers; - ndrivers =3D VIRT_N_ELEMENTS(systemDrivers); + if (sessionOpt) { + busType =3D G_BUS_TYPE_SESSION; + } else if (systemOpt) { + busType =3D G_BUS_TYPE_SYSTEM; } else { - drivers =3D sessionDrivers; - ndrivers =3D VIRT_N_ELEMENTS(sessionDrivers); + if (geteuid() =3D=3D 0) { + busType =3D G_BUS_TYPE_SYSTEM; + } else { + busType =3D G_BUS_TYPE_SESSION; + } } =20 - connect =3D calloc(ndrivers + 1, sizeof(virtDBusConnect *)); - - for (int i =3D 0; i < ndrivers; i +=3D 1) { - r =3D virtDBusConnectNew(&connect[i], bus, - drivers[i].uri, drivers[i].object); - if (r < 0) { - fprintf(stderr, "Failed to register libvirt connection.\n"); - return EXIT_FAILURE; - } + if (busType =3D=3D G_BUS_TYPE_SYSTEM) { + data.drivers =3D systemDrivers; + data.ndrivers =3D G_N_ELEMENTS(systemDrivers); + } else { + data.drivers =3D sessionDrivers; + data.ndrivers =3D G_N_ELEMENTS(sessionDrivers); } + data.connectList =3D g_new0(virtDBusConnect *, data.ndrivers + 1); + g_assert(data.connectList); =20 - r =3D virtDBusProcessEvents(bus); - if (r < 0) - return EXIT_FAILURE; + loop =3D g_main_loop_new(NULL, FALSE); =20 - bus_watch =3D virEventAddHandle(sd_bus_get_fd(bus), - virtDBusGetLibvirtEvents(bus), - virtDBusHandleBusEvent, - bus, - NULL); + sigtermSource =3D g_unix_signal_add(SIGTERM, + virtDBusHandleSignal, + loop); =20 - signal_fd =3D signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); - signal_watch =3D virEventAddHandle(signal_fd, - VIR_EVENT_HANDLE_READABLE, + sigintSource =3D g_unix_signal_add(SIGINT, virtDBusHandleSignal, - NULL, - NULL); - if (signal_watch < 0) { - fprintf(stderr, "Failed to register signal handler.\n"); - return EXIT_FAILURE; - } + loop); =20 - while (loop_status >=3D 0) - virEventRunDefaultImpl(); + gvir_init(0, NULL); + gvir_event_register(); =20 - if (loop_status < 0 && loop_status !=3D -ECANCELED) { - fprintf(stderr, "Error: %s\n", strerror(-loop_status)); - return EXIT_FAILURE; - } + busOwner =3D g_bus_own_name(busType, "org.libvirt", + G_BUS_NAME_OWNER_FLAGS_NONE, + virtDBusAcquired, + virtDBusNameAcquired, + virtDBusNameLost, + &data, NULL); + + g_main_loop_run(loop); =20 return EXIT_SUCCESS; } diff --git a/src/util.c b/src/util.c index 9042a0f..c0b5bbe 100644 --- a/src/util.c +++ b/src/util.c @@ -1,155 +1,129 @@ #include "util.h" =20 #include -#include -#include +#include =20 -int -virtDBusUtilMessageAppendTypedParameters(sd_bus_message *message, - virTypedParameterPtr parameters, - int n_parameters) +static const GDBusErrorEntry virtDBusUtilErrorEntries[] =3D { + { VIRT_DBUS_ERROR_LIBVIRT, "org.libvirt.Error" }, +}; + +G_STATIC_ASSERT(G_N_ELEMENTS(virtDBusUtilErrorEntries) =3D=3D VIRT_DBUS_N_= ERRORS); + +GQuark +virtDBusErrorQuark(void) { - int r; + static volatile gsize quarkVolatile =3D 0; + g_dbus_error_register_error_domain("virt-dbus-error-quark", + &quarkVolatile, + virtDBusUtilErrorEntries, + G_N_ELEMENTS(virtDBusUtilErrorEntri= es)); + return (GQuark) quarkVolatile; +} =20 - r =3D sd_bus_message_open_container(message, 'a', "{sv}"); - if (r < 0) - return r; +GVariant * +virtDBusUtilTypedParamsToGVariant(virTypedParameterPtr params, + gint nparams) +{ + GVariantBuilder builder; =20 - for (int i =3D 0; i < n_parameters; i +=3D 1) { - r =3D sd_bus_message_open_container(message, SD_BUS_TYPE_DICT_ENTR= Y, "sv"); - if (r < 0) - return r; + g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}")); =20 - r =3D sd_bus_message_append(message, "s", parameters[i].field); - if (r < 0) - return r; + for (gint i =3D 0; i < nparams; i++) { + GVariant *value =3D NULL; =20 - switch (parameters[i].type) { + switch (params[i].type) { case VIR_TYPED_PARAM_INT: - r =3D sd_bus_message_append(message, "v", "i", parameters[i].v= alue.i); + value =3D g_variant_new("i", params[i].value.i); break; case VIR_TYPED_PARAM_UINT: - r =3D sd_bus_message_append(message, "v", "u", parameters[i].v= alue.ui); + value =3D g_variant_new("u", params[i].value.ui); break; case VIR_TYPED_PARAM_LLONG: - r =3D sd_bus_message_append(message, "v", "x", parameters[i].v= alue.l); + value =3D g_variant_new("x", params[i].value.l); break; case VIR_TYPED_PARAM_ULLONG: - r =3D sd_bus_message_append(message, "v", "t", parameters[i].v= alue.ul); + value =3D g_variant_new("t", params[i].value.ul); break; case VIR_TYPED_PARAM_DOUBLE: - r =3D sd_bus_message_append(message, "v", "d", parameters[i].v= alue.d); + value =3D g_variant_new("d", params[i].value.d); break; case VIR_TYPED_PARAM_BOOLEAN: - r =3D sd_bus_message_append(message, "v", "b", parameters[i].v= alue.b); + value =3D g_variant_new("b", params[i].value.b); break; case VIR_TYPED_PARAM_STRING: - r =3D sd_bus_message_append(message, "v", "s", parameters[i].v= alue.s); + value =3D g_variant_new("s", params[i].value.s); break; } =20 - if (r < 0) - return r; - - r =3D sd_bus_message_close_container(message); - if (r < 0) - return r; + g_variant_builder_add(&builder, "{sv}", + params[i].field, + g_variant_new_variant(value)); } =20 - return sd_bus_message_close_container(message); + return g_variant_builder_end(&builder); } =20 -int -virtDBusUtilSetLastVirtError(sd_bus_error *error) +void +virtDBusUtilSetLastVirtError(GError **error) { virErrorPtr vir_error; =20 vir_error =3D virGetLastError(); - if (!vir_error) - return 0; + if (!vir_error) { + g_set_error(error, VIRT_DBUS_ERROR, VIRT_DBUS_ERROR_LIBVIRT, + "unknown error"); + } else { + g_set_error_literal(error, VIRT_DBUS_ERROR, VIRT_DBUS_ERROR_LIBVIR= T, + vir_error->message); + } +} =20 - return sd_bus_error_set(error, VIRT_DBUS_ERROR_INTERFACE, vir_error->m= essage); +static gchar * +virtDBusUtilEncodeUUID(const gchar *uuid) +{ + gchar *ret =3D g_strdup_printf("_%s", uuid); + g_assert(ret); + return g_strdelimit(ret, "-", '_'); } =20 -int -virtDBusUtilSetError(sd_bus_error *error, - const char *message) +static gchar * +virtDBusUtilDecodeUUID(const gchar *uuid) { - return sd_bus_error_set(error, VIRT_DBUS_ERROR_INTERFACE, message); + gchar *ret =3D g_strdup(uuid+1); + g_assert(ret); + return g_strdelimit(ret, "_", '-'); } =20 -char * +gchar * virtDBusUtilBusPathForVirDomain(virDomainPtr domain, - const char *domainPath) + const gchar *domainPath) { - char *path =3D NULL; - char uuid[VIR_UUID_STRING_BUFLEN] =3D ""; - + gchar uuid[VIR_UUID_STRING_BUFLEN] =3D ""; + g_autofree gchar *newUuid =3D NULL; virDomainGetUUIDString(domain, uuid); - sd_bus_path_encode(domainPath, uuid, &path); - - return path; + newUuid =3D virtDBusUtilEncodeUUID(uuid); + return g_strdup_printf("%s/%s", domainPath, newUuid); } =20 virDomainPtr virtDBusUtilVirDomainFromBusPath(virConnectPtr connection, - const char *path, - const char *domainPath) + const gchar *path, + const gchar *domainPath) { - _cleanup_(virtDBusUtilFreep) char *name =3D NULL; - int r; + g_autofree gchar *name =3D NULL; + gsize prefixLen =3D strlen(domainPath) + 1; =20 - r =3D sd_bus_path_decode(path, domainPath, &name); - if (r < 0) - return NULL; + name =3D virtDBusUtilDecodeUUID(path+prefixLen); + g_assert(name); =20 return virDomainLookupByUUIDString(connection, name); } =20 void -virtDBusUtilFreep(void *p) -{ - free(*(void **)p); -} - -void -virtDBusUtilClosep(int *fdp) -{ - if (*fdp >=3D 0) - close(*fdp); -} - -void -virtDBusUtilStrvFreep(void *p) -{ - char **strv =3D *(char ***)p; - - if (strv =3D=3D NULL) - return; - - for (unsigned i =3D 0; strv[i] !=3D NULL; i++) - free(strv[i]); - - free(strv); -} - -void -virtDBusUtilVirDomainFreep(virDomainPtr *domainp) -{ - if (*domainp) - virDomainFree(*domainp); -} - -void -virtDBusUtilVirDomainListFreep(virDomainPtr **domainsp) +virtDBusUtilVirDomainListFree(virDomainPtr *domains) { - virDomainPtr *domains =3D *domainsp; - - if (!domains) - return; - - for (int i =3D 0; domains[i] !=3D NULL; i +=3D 1) + for (gint i =3D 0; domains[i] !=3D NULL; i +=3D 1) virDomainFree(domains[i]); =20 - free(domains); + g_free(domains); } diff --git a/src/util.h b/src/util.h index 2a6f7e2..8cafafa 100644 --- a/src/util.h +++ b/src/util.h @@ -1,49 +1,38 @@ #pragma once =20 -#include -#include - -#define VIRT_DBUS_ERROR_INTERFACE "org.libvirt.Error" - -#define _cleanup_(_x) __attribute__((__cleanup__(_x))) +#include "gdbus.h" =20 -#define VIRT_ATTR_UNUSED __attribute__((__unused__)) +#include =20 -#define VIRT_N_ELEMENTS(array) (sizeof(array) / sizeof(*(array))) +#define VIRT_DBUS_ERROR virtDBusErrorQuark() =20 +typedef enum { + VIRT_DBUS_ERROR_LIBVIRT, + VIRT_DBUS_N_ERRORS /*< skip >*/ +} VirtDBusError; =20 -int -virtDBusUtilMessageAppendTypedParameters(sd_bus_message *message, - virTypedParameterPtr parameters, - int n_parameters); +GQuark +virtDBusErrorQuark(void); =20 -int -virtDBusUtilSetLastVirtError(sd_bus_error *error); +GVariant * +virtDBusUtilTypedParamsToGVariant(virTypedParameterPtr params, + gint nparams); =20 -int -virtDBusUtilSetError(sd_bus_error *error, - const char *message); +void +virtDBusUtilSetLastVirtError(GError **error); =20 -char * +gchar * virtDBusUtilBusPathForVirDomain(virDomainPtr domain, - const char *domainPath); + const gchar *domainPath); =20 virDomainPtr virtDBusUtilVirDomainFromBusPath(virConnectPtr connection, - const char *path, - const char *domainPath); + const gchar *path, + const gchar *domainPath); =20 void -virtDBusUtilFreep(void *p); +virtDBusUtilVirDomainListFree(virDomainPtr *domains); =20 -void -virtDBusUtilClosep(int *fdp); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomain, virDomainFree); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainPtr, virtDBusUtilVirDomainListFree); =20 -void -virtDBusUtilStrvFreep(void *p); - -void -virtDBusUtilVirDomainFreep(virDomainPtr *domainp); - -void -virtDBusUtilVirDomainListFreep(virDomainPtr **domainsp); diff --git a/test/travis-run b/test/travis-run index 28260f4..7577253 100755 --- a/test/travis-run +++ b/test/travis-run @@ -22,7 +22,7 @@ sudo chroot "$CHROOT" << EOF set -ex # install build deps apt-get update -apt-get install -y dh-autoreconf pkg-config libvirt-dev libsystemd-dev lib= glib2.0-dev libtool python3-gi python3-dbus dbus +apt-get install -y dh-autoreconf pkg-config libvirt-dev libglib2.0-dev lib= tool python3-gi python3-dbus dbus =20 # run build and tests as user chown -R buildd:buildd /build --=20 2.14.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sun May 5 21:53:28 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1521548122987856.5142454671594; Tue, 20 Mar 2018 05:15:22 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 71D505F7B8; Tue, 20 Mar 2018 12:15:21 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 3BB8E189F9; Tue, 20 Mar 2018 12:15:21 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id F17EB4CA9A; Tue, 20 Mar 2018 12:15:20 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w2KCFIPa028445 for ; Tue, 20 Mar 2018 08:15:18 -0400 Received: by smtp.corp.redhat.com (Postfix) id F1A29200BCAE; Tue, 20 Mar 2018 12:15:17 +0000 (UTC) Received: from antique-work.brq.redhat.com (unknown [10.43.2.152]) by smtp.corp.redhat.com (Postfix) with ESMTP id 98E28202322F for ; Tue, 20 Mar 2018 12:15:17 +0000 (UTC) From: Pavel Hrdina To: libvir-list@redhat.com Date: Tue, 20 Mar 2018 13:15:14 +0100 Message-Id: <7838f67b6254aa903dfc022299ba20338f8ab657.1521547610.git.phrdina@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-loop: libvir-list@redhat.com Subject: [libvirt] [dbus PATCH v2 3/3] main: introduce thread pool to process D-Bus messages X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 20 Mar 2018 12:15:22 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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 --- 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 b3ead76..aa11f69 100644 --- a/src/connect.c +++ b/src/connect.c @@ -56,6 +56,8 @@ gboolean virtDBusConnectOpen(virtDBusConnect *connect, GError **error) { + g_autoptr(GMutexLocker) lock =3D g_mutex_locker_new(&connect->lock); + if (connect->connection) { if (virConnectIsAlive(connect->connection)) return TRUE; @@ -211,6 +213,8 @@ virtDBusConnectNew(virtDBusConnect **connectp, connect =3D g_new0(virtDBusConnect, 1); g_assert(connect !=3D NULL); =20 + g_mutex_init(&connect->lock); + for (gint i =3D 0; i < VIR_DOMAIN_EVENT_ID_LAST; i +=3D 1) connect->callback_ids[i] =3D -1; =20 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; =20 gint callback_ids[VIR_DOMAIN_EVENT_ID_LAST]; }; diff --git a/src/gdbus.c b/src/gdbus.c index de02415..a814fe3 100644 --- a/src/gdbus.c +++ b/src/gdbus.c @@ -16,6 +16,16 @@ struct _virtDBusGDBusSubtreeData { }; typedef struct _virtDBusGDBusSubtreeData virtDBusGDBusSubtreeData; =20 +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 =3D NULL; =20 /** @@ -222,6 +232,38 @@ virtDBusGDBusHandleMethod(GVariant *parameters, outFDs); } =20 +static void +virtDBusGDBusMethodCallThread(gpointer threadData, + gpointer userData G_GNUC_UNUSED) +{ + g_autofree virtDBusGDBusThreadData *data =3D threadData; + + if (g_strcmp0(data->interfaceName, "org.freedesktop.DBus.Properties") = =3D=3D 0) { + if (g_strcmp0(data->methodName, "Get") =3D=3D 0) { + virtDBusGDBusHandlePropertyGet(data->parameters, data->invocat= ion, + data->objectPath, data->methodD= ata); + } else if (g_strcmp0(data->methodName, "Set") =3D=3D 0) { + virtDBusGDBusHandlePropertySet(data->parameters, data->invocat= ion, + data->objectPath, data->methodD= ata); + } else if (g_strcmp0(data->methodName, "GetAll") =3D=3D 0) { + virtDBusGDBusHandlePropertyGetAll(data->invocation, data->obje= ctPath, + data->methodData); + } else { + g_dbus_method_invocation_return_error(data->invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_UNKNOWN_MET= HOD, + "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, @@ -232,27 +274,18 @@ virtDBusGDBusHandleMethodCall(GDBusConnection *connec= tion G_GNUC_UNUSED, GDBusMethodInvocation *invocation, gpointer userData) { - virtDBusGDBusMethodData *data =3D userData; - - if (g_strcmp0(interfaceName, "org.freedesktop.DBus.Properties") =3D=3D= 0) { - if (g_strcmp0(methodName, "Get") =3D=3D 0) { - virtDBusGDBusHandlePropertyGet(parameters, invocation, - objectPath, data); - } else if (g_strcmp0(methodName, "Set") =3D=3D 0) { - virtDBusGDBusHandlePropertySet(parameters, invocation, - objectPath, data); - } else if (g_strcmp0(methodName, "GetAll") =3D=3D 0) { - virtDBusGDBusHandlePropertyGetAll(invocation, objectPath, data= ); - } else { - g_dbus_method_invocation_return_error(invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_UNKNOWN_MET= HOD, - "unknown method '%s'", m= ethodName); - } - } else { - virtDBusGDBusHandleMethod(parameters, invocation, objectPath, - methodName, data); - } + virtDBusGDBusThreadData *data =3D g_new0(virtDBusGDBusThreadData, 1); + + g_assert(data); + + data->objectPath =3D objectPath; + data->interfaceName =3D interfaceName; + data->methodName =3D methodName; + data->parameters =3D parameters; + data->invocation =3D invocation; + data->methodData =3D userData; + + g_thread_pool_push(threadPool, data, NULL); } =20 static const GDBusInterfaceVTable virtDBusGDBusVtable =3D { @@ -399,3 +432,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 =3D g_thread_pool_new(virtDBusGDBusMethodCallThread, + NULL, + maxThreads, + FALSE, + error); + + return !!threadPool; +} diff --git a/src/gdbus.h b/src/gdbus.h index b9c71cc..ccf06df 100644 --- a/src/gdbus.h +++ b/src/gdbus.h @@ -103,5 +103,9 @@ virtDBusGDBusRegisterSubtree(GDBusConnection *bus, virtDBusGDBusPropertyTable *properties, gpointer userData); =20 +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 72a7e21..fe11058 100644 --- a/src/main.c +++ b/src/main.c @@ -83,11 +83,14 @@ virtDBusRegisterDataFree(virtDBusRegisterData *data) } G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(virtDBusRegisterData, virtDBusRegisterDat= aFree); =20 +#define VIRT_DBUS_MAX_THREADS 4 + int main(gint argc, gchar *argv[]) { static gboolean systemOpt =3D FALSE; static gboolean sessionOpt =3D FALSE; + static gint maxThreads =3D VIRT_DBUS_MAX_THREADS; GBusType busType; g_auto(virtDBusGDBusSource) sigintSource =3D 0; g_auto(virtDBusGDBusSource) sigtermSource =3D 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 } }; =20 @@ -140,6 +145,11 @@ main(gint argc, gchar *argv[]) data.connectList =3D g_new0(virtDBusConnect *, data.ndrivers + 1); g_assert(data.connectList); =20 + if (!virtDBusGDBusPrepareThreadPool(maxThreads, &error)) { + g_printerr("%s\n", error->message); + exit(EXIT_FAILURE); + } + loop =3D g_main_loop_new(NULL, FALSE); =20 sigtermSource =3D g_unix_signal_add(SIGTERM, --=20 2.14.3 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list