[PATCH] libnm-glib async patches
- From: Dan Winship <danw gnome org>
- To: networkmanager-list gnome org
- Subject: [PATCH] libnm-glib async patches
- Date: Wed, 01 Feb 2012 09:27:21 -0500
depends on the previous two patch sets
With just the first patch, libnm-glib users will completely avoid
synchronous D-Bus calls after the initial nm_client_new() /
nm_remote_settings_new() calls. The patches to add async constructors
for those types allow getting rid of the synchronous D-Bus calls at
startup as well.
>From c2b85a0fa4785ef13290eefcc75f7a39c42d59b3 Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Tue, 20 Dec 2011 15:15:42 -0500
Subject: [PATCH 10/12] libnm-glib: Implement GInitable/GAsyncInitable in
NMObject
Implement GInitable and GAsyncInitable in NMObject, with
implementations that synchronously or asynchonously load all
properties, and change _nm_object_ensure_inited() to run
g_initable_init().
Update the object/object-array property handling to initialize the
objects after creating them (synchronously or asynchronously,
according to the situation), so that they will have all of their
properties preloaded before they are ever visible to the caller.
Move the non-blocking/non-failable parts of various objects'
constructor() methods to constructed(), and move the blocking/failable
parts to init(), and implement init_async() methods with non-blocking
versions of the blocking methods.
Make nm_device_new() and nm_client_new() call
_nm_object_ensure_inited(), to preserve the behaviour formerly
enforced by their construct() methods, that properties are guaranteed
to be initialized before any signals involving them are emitted.
---
libnm-glib/Makefile.am | 16 +-
libnm-glib/nm-access-point.c | 21 +--
libnm-glib/nm-active-connection.c | 21 +--
libnm-glib/nm-client.c | 213 +++++++++++++++++-----
libnm-glib/nm-device-bt.c | 29 +--
libnm-glib/nm-device-ethernet.c | 29 ++--
libnm-glib/nm-device-infiniband.c | 29 ++--
libnm-glib/nm-device-modem.c | 28 +--
libnm-glib/nm-device-wifi.c | 36 ++---
libnm-glib/nm-device-wimax.c | 29 ++--
libnm-glib/nm-device.c | 85 ++--------
libnm-glib/nm-dhcp4-config.c | 21 +--
libnm-glib/nm-dhcp6-config.c | 21 +--
libnm-glib/nm-ip4-config.c | 21 +--
libnm-glib/nm-ip6-config.c | 17 +--
libnm-glib/nm-object-private.h | 10 +-
libnm-glib/nm-object.c | 360 +++++++++++++++++++++++++++++++++----
libnm-glib/nm-remote-connection.c | 14 +--
libnm-glib/nm-remote-settings.c | 14 +--
libnm-glib/nm-vpn-connection.c | 21 +--
libnm-glib/nm-wimax-nsp.c | 21 +--
21 files changed, 636 insertions(+), 420 deletions(-)
diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am
index 318a463..7bf4fef 100644
--- a/libnm-glib/Makefile.am
+++ b/libnm-glib/Makefile.am
@@ -43,7 +43,7 @@ libdeprecated_HEADERS = libnm_glib.h
lib_LTLIBRARIES = libnm-glib.la libnm-glib-vpn.la
libnm_glib_la_CFLAGS = \
- $(GLIB_CFLAGS) \
+ $(GIO_CFLAGS) \
$(DBUS_CFLAGS) \
$(GUDEV_CFLAGS)
@@ -117,7 +117,7 @@ libnm_glib_la_LIBADD = \
$(top_builddir)/libnm-util/libnm-util.la \
$(top_builddir)/marshallers/libmarshallers.la \
$(builddir)/libdeprecated-nm-glib.la \
- $(GLIB_LIBS) \
+ $(GIO_LIBS) \
$(DBUS_LIBS) \
$(GUDEV_LIBS)
@@ -129,16 +129,16 @@ libnm_glib_la_LDFLAGS = -Wl,--version-script=$(SYMBOL_VIS_FILE) \
noinst_PROGRAMS = libnm-glib-test
libnm_glib_test_SOURCES = libnm-glib-test.c
-libnm_glib_test_CFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS)
-libnm_glib_test_LDADD = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la $(GLIB_LIBS) $(DBUS_LIBS)
+libnm_glib_test_CFLAGS = $(GIO_CFLAGS) $(DBUS_CFLAGS)
+libnm_glib_test_LDADD = libnm-glib.la $(top_builddir)/libnm-util/libnm-util.la $(GIO_LIBS) $(DBUS_LIBS)
libnm_glib_vpn_la_SOURCES = \
nm-vpn-plugin.c \
nm-vpn-plugin-ui-interface.c \
nm-vpn-plugin-utils.c
-libnm_glib_vpn_la_CFLAGS = $(GLIB_CFLAGS) $(DBUS_CFLAGS)
-libnm_glib_vpn_la_LIBADD = $(top_builddir)/libnm-util/libnm-util.la $(GLIB_LIBS) $(DBUS_LIBS)
+libnm_glib_vpn_la_CFLAGS = $(GIO_CFLAGS) $(DBUS_CFLAGS)
+libnm_glib_vpn_la_LIBADD = $(top_builddir)/libnm-util/libnm-util.la $(GIO_LIBS) $(DBUS_LIBS)
libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \
-version-info "2:0:1"
@@ -147,7 +147,7 @@ libnm_glib_vpn_la_LDFLAGS = -Wl,--version-script=$(srcdir)/libnm-glib-vpn.ver \
#####################################################
libnm_glib_test_la_CFLAGS = \
- $(GLIB_CFLAGS) \
+ $(GIO_CFLAGS) \
$(DBUS_CFLAGS) \
$(GUDEV_CFLAGS) \
-DLIBNM_GLIB_TEST
@@ -159,7 +159,7 @@ libnm_glib_test_la_SOURCES = \
libnm_glib_test_la_LIBADD = \
$(top_builddir)/libnm-util/libnm-util.la \
$(top_builddir)/marshallers/libmarshallers.la \
- $(GLIB_LIBS) \
+ $(GIO_LIBS) \
$(DBUS_LIBS) \
$(GUDEV_LIBS)
diff --git a/libnm-glib/nm-access-point.c b/libnm-glib/nm-access-point.c
index 9a25365..53993b0 100644
--- a/libnm-glib/nm-access-point.c
+++ b/libnm-glib/nm-access-point.c
@@ -533,30 +533,21 @@ register_properties (NMAccessPoint *ap)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- NMObject *object;
NMAccessPointPrivate *priv;
- object = (NMObject *) G_OBJECT_CLASS (nm_access_point_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_access_point_parent_class)->constructed (object);
priv = NM_ACCESS_POINT_GET_PRIVATE (object);
- priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+ priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE_ACCESS_POINT);
register_properties (NM_ACCESS_POINT (object));
-
- return G_OBJECT (object);
}
@@ -568,7 +559,7 @@ nm_access_point_class_init (NMAccessPointClass *ap_class)
g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
diff --git a/libnm-glib/nm-active-connection.c b/libnm-glib/nm-active-connection.c
index 0c922b7..9c5be58 100644
--- a/libnm-glib/nm-active-connection.c
+++ b/libnm-glib/nm-active-connection.c
@@ -445,30 +445,21 @@ register_properties (NMActiveConnection *connection)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- NMObject *object;
NMActiveConnectionPrivate *priv;
- object = (NMObject *) G_OBJECT_CLASS (nm_active_connection_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_active_connection_parent_class)->constructed (object);
priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (object);
- priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+ priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE_ACTIVE_CONNECTION);
register_properties (NM_ACTIVE_CONNECTION (object));
-
- return G_OBJECT (object);
}
@@ -480,7 +471,7 @@ nm_active_connection_class_init (NMActiveConnectionClass *ap_class)
g_type_class_add_private (ap_class, sizeof (NMActiveConnectionPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c
index 1178dbb..f27521d 100644
--- a/libnm-glib/nm-client.c
+++ b/libnm-glib/nm-client.c
@@ -39,7 +39,15 @@
void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
-G_DEFINE_TYPE (NMClient, nm_client, NM_TYPE_OBJECT)
+static void nm_client_initable_iface_init (GInitableIface *iface);
+static void nm_client_async_initable_iface_init (GAsyncInitableIface *iface);
+static GInitableIface *nm_client_parent_initable_iface;
+static GAsyncInitableIface *nm_client_parent_async_initable_iface;
+
+G_DEFINE_TYPE_WITH_CODE (NMClient, nm_client, NM_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_client_initable_iface_init);
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_client_async_initable_iface_init);
+ )
#define NM_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CLIENT, NMClientPrivate))
@@ -372,19 +380,21 @@ update_permissions (NMClient *self, GHashTable *permissions)
g_list_free (keys);
}
-static void
-get_permissions_sync (NMClient *self)
+static gboolean
+get_permissions_sync (NMClient *self, GError **error)
{
gboolean success;
GHashTable *permissions = NULL;
success = dbus_g_proxy_call_with_timeout (NM_CLIENT_GET_PRIVATE (self)->client_proxy,
- "GetPermissions", 3000, NULL,
+ "GetPermissions", 3000, error,
G_TYPE_INVALID,
DBUS_TYPE_G_MAP_OF_STRING, &permissions, G_TYPE_INVALID);
update_permissions (self, success ? permissions : NULL);
if (permissions)
g_hash_table_destroy (permissions);
+
+ return success;
}
static void
@@ -1191,6 +1201,7 @@ nm_client_new (void)
{
DBusGConnection *connection;
GError *err = NULL;
+ NMClient *client;
#ifdef LIBNM_GLIB_TEST
connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
@@ -1203,34 +1214,28 @@ nm_client_new (void)
return NULL;
}
- return (NMClient *) g_object_new (NM_TYPE_CLIENT,
- NM_OBJECT_DBUS_CONNECTION, connection,
- NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
- NULL);
+ client = g_object_new (NM_TYPE_CLIENT,
+ NM_OBJECT_DBUS_CONNECTION, connection,
+ NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
+ NULL);
+ _nm_object_ensure_inited (NM_OBJECT (client));
+ return client;
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- NMObject *object;
DBusGConnection *connection;
NMClientPrivate *priv;
- GError *err = NULL;
- object = (NMObject *) G_OBJECT_CLASS (nm_client_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_client_parent_class)->constructed (object);
priv = NM_CLIENT_GET_PRIVATE (object);
- connection = nm_object_get_connection (object);
+ connection = nm_object_get_connection (NM_OBJECT (object));
priv->client_proxy = dbus_g_proxy_new_for_name (connection,
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE);
register_properties (NM_CLIENT (object));
@@ -1242,7 +1247,6 @@ constructor (GType type,
G_CALLBACK (client_recheck_permissions),
object,
NULL);
- get_permissions_sync (NM_CLIENT (object));
priv->bus_proxy = dbus_g_proxy_new_for_name (connection,
DBUS_SERVICE_DBUS,
@@ -1257,38 +1261,136 @@ constructor (GType type,
G_CALLBACK (proxy_name_owner_changed),
object, NULL);
+ g_signal_connect (object, "notify::" NM_CLIENT_WIRELESS_ENABLED,
+ G_CALLBACK (wireless_enabled_cb), NULL);
+
+ g_signal_connect (object, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
+ G_CALLBACK (active_connections_changed_cb), NULL);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+ NMClient *client = NM_CLIENT (initable);
+ NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
+
+ if (!nm_client_parent_initable_iface->init (initable, cancellable, error))
+ return FALSE;
+
if (!dbus_g_proxy_call (priv->bus_proxy,
- "NameHasOwner", &err,
- G_TYPE_STRING, NM_DBUS_SERVICE,
- G_TYPE_INVALID,
- G_TYPE_BOOLEAN, &priv->manager_running,
- G_TYPE_INVALID)) {
- g_warning ("Error on NameHasOwner DBUS call: %s", err->message);
- g_error_free (err);
- }
+ "NameHasOwner", error,
+ G_TYPE_STRING, NM_DBUS_SERVICE,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &priv->manager_running,
+ G_TYPE_INVALID))
+ return FALSE;
+
+ if (priv->manager_running && !get_permissions_sync (client, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+typedef struct {
+ NMClient *client;
+ GSimpleAsyncResult *result;
+ gboolean properties_pending;
+ gboolean permissions_pending;
+} NMClientInitData;
+
+static void
+init_async_complete (NMClientInitData *init_data)
+{
+ if (init_data->properties_pending || init_data->permissions_pending)
+ return;
+
+ g_simple_async_result_complete (init_data->result);
+ g_object_unref (init_data->result);
+ g_slice_free (NMClientInitData, init_data);
+}
+
+static void
+init_async_got_permissions (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+{
+ NMClientInitData *init_data = user_data;
+ GHashTable *permissions;
+ GError *error = NULL;
+
+ dbus_g_proxy_end_call (proxy, call, &error,
+ DBUS_TYPE_G_MAP_OF_STRING, &permissions,
+ G_TYPE_INVALID);
+ update_permissions (init_data->client, error ? NULL : permissions);
+ g_clear_error (&error);
+
+ init_data->permissions_pending = FALSE;
+ init_async_complete (init_data);
+}
+
+static void
+init_async_got_properties (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ NMClientInitData *init_data = user_data;
+ GError *error = NULL;
- if (priv->manager_running) {
- update_wireless_status (NM_CLIENT (object), FALSE);
- update_wwan_status (NM_CLIENT (object), FALSE);
- update_wimax_status (NM_CLIENT (object), FALSE);
- nm_client_get_state (NM_CLIENT (object));
+ if (!nm_client_parent_async_initable_iface->init_finish (G_ASYNC_INITABLE (source), result, &error))
+ g_simple_async_result_take_error (init_data->result, error);
+
+ init_data->properties_pending = FALSE;
+ init_async_complete (init_data);
+}
+
+static void
+init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
+ gpointer user_data)
+{
+ NMClientInitData *init_data = user_data;
+ NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (init_data->client);
+ GError *error = NULL;
+
+ if (!dbus_g_proxy_end_call (proxy, call, &error,
+ G_TYPE_BOOLEAN, &priv->manager_running,
+ G_TYPE_INVALID)) {
+ g_simple_async_result_take_error (init_data->result, error);
+ init_async_complete (init_data);
+ return;
}
- g_signal_connect (G_OBJECT (object), "notify::" NM_CLIENT_WIRELESS_ENABLED,
- G_CALLBACK (wireless_enabled_cb), NULL);
+ if (!priv->manager_running) {
+ g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+ init_async_complete (init_data);
+ return;
+ }
- g_signal_connect (object, "notify::" NM_CLIENT_ACTIVE_CONNECTIONS,
- G_CALLBACK (active_connections_changed_cb), NULL);
+ nm_client_parent_async_initable_iface->init_async (G_ASYNC_INITABLE (init_data->client),
+ G_PRIORITY_DEFAULT, NULL, /* FIXME cancellable */
+ init_async_got_properties, init_data);
+ init_data->properties_pending = TRUE;
- /* Get initial devices from NM. It is important to do it early. Else,
- * a 'lazy' call won't find removed device.
- * Solves this case: DeviceRemoved signal is received, we get devices
- * from NM, but the removed object path is not there any more, and
- * NMClient doesn't have the device either.
- */
- nm_client_get_devices (NM_CLIENT (object));
+ dbus_g_proxy_begin_call (priv->client_proxy, "GetPermissions",
+ init_async_got_permissions, init_data, NULL,
+ G_TYPE_INVALID);
+ init_data->permissions_pending = TRUE;
+}
- return G_OBJECT (object);
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+ GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ NMClientInitData *init_data;
+ NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (initable);
+
+ init_data = g_slice_new0 (NMClientInitData);
+ init_data->client = NM_CLIENT (initable);
+ init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
+ user_data, init_async);
+
+ /* Check if NM is running */
+ dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner",
+ init_async_got_manager_running,
+ init_data, NULL,
+ G_TYPE_STRING, NM_DBUS_SERVICE,
+ G_TYPE_INVALID);
}
static void
@@ -1427,7 +1529,7 @@ nm_client_class_init (NMClientClass *client_class)
g_type_class_add_private (client_class, sizeof (NMClientPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
@@ -1631,3 +1733,18 @@ nm_client_class_init (NMClientClass *client_class)
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
}
+static void
+nm_client_initable_iface_init (GInitableIface *iface)
+{
+ nm_client_parent_initable_iface = g_type_interface_peek_parent (iface);
+
+ iface->init = init_sync;
+}
+
+static void
+nm_client_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+ nm_client_parent_async_initable_iface = g_type_interface_peek_parent (iface);
+
+ iface->init_async = init_async;
+}
diff --git a/libnm-glib/nm-device-bt.c b/libnm-glib/nm-device-bt.c
index 4c9f955..581d1d0 100644
--- a/libnm-glib/nm-device-bt.c
+++ b/libnm-glib/nm-device-bt.c
@@ -216,28 +216,19 @@ register_properties (NMDeviceBt *device)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
-
- object = G_OBJECT_CLASS (nm_device_bt_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (object) {
- NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object);
+ NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object);
- priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
- NM_DBUS_SERVICE,
- nm_object_get_path (NM_OBJECT (object)),
- NM_DBUS_INTERFACE_DEVICE_BLUETOOTH);
+ G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object);
- register_properties (NM_DEVICE_BT (object));
- }
+ priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
+ NM_DBUS_SERVICE,
+ nm_object_get_path (NM_OBJECT (object)),
+ NM_DBUS_INTERFACE_DEVICE_BLUETOOTH);
- return object;
+ register_properties (NM_DEVICE_BT (object));
}
static void
@@ -300,7 +291,7 @@ nm_device_bt_class_init (NMDeviceBtClass *bt_class)
g_type_class_add_private (bt_class, sizeof (NMDeviceBtPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->dispose = dispose;
object_class->finalize = finalize;
object_class->get_property = get_property;
diff --git a/libnm-glib/nm-device-ethernet.c b/libnm-glib/nm-device-ethernet.c
index c043113..1dd45f3 100644
--- a/libnm-glib/nm-device-ethernet.c
+++ b/libnm-glib/nm-device-ethernet.c
@@ -75,13 +75,17 @@ enum {
GObject *
nm_device_ethernet_new (DBusGConnection *connection, const char *path)
{
+ GObject *device;
+
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
- return g_object_new (NM_TYPE_DEVICE_ETHERNET,
- NM_OBJECT_DBUS_CONNECTION, connection,
- NM_OBJECT_DBUS_PATH, path,
- NULL);
+ device = g_object_new (NM_TYPE_DEVICE_ETHERNET,
+ NM_OBJECT_DBUS_CONNECTION, connection,
+ NM_OBJECT_DBUS_PATH, path,
+ NULL);
+ _nm_object_ensure_inited (NM_OBJECT (device));
+ return device;
}
/**
@@ -224,19 +228,12 @@ register_properties (NMDeviceEthernet *device)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
NMDeviceEthernetPrivate *priv;
- object = G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_device_ethernet_parent_class)->constructed (object);
priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
@@ -246,8 +243,6 @@ constructor (GType type,
NM_DBUS_INTERFACE_DEVICE_WIRED);
register_properties (NM_DEVICE_ETHERNET (object));
-
- return object;
}
static void
@@ -314,7 +309,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *eth_class)
g_type_class_add_private (eth_class, sizeof (NMDeviceEthernetPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->dispose = dispose;
object_class->finalize = finalize;
object_class->get_property = get_property;
diff --git a/libnm-glib/nm-device-infiniband.c b/libnm-glib/nm-device-infiniband.c
index 384a348..9ac3825 100644
--- a/libnm-glib/nm-device-infiniband.c
+++ b/libnm-glib/nm-device-infiniband.c
@@ -68,13 +68,17 @@ enum {
GObject *
nm_device_infiniband_new (DBusGConnection *connection, const char *path)
{
+ GObject *device;
+
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
- return g_object_new (NM_TYPE_DEVICE_INFINIBAND,
- NM_OBJECT_DBUS_CONNECTION, connection,
- NM_OBJECT_DBUS_PATH, path,
- NULL);
+ device = g_object_new (NM_TYPE_DEVICE_INFINIBAND,
+ NM_OBJECT_DBUS_CONNECTION, connection,
+ NM_OBJECT_DBUS_PATH, path,
+ NULL);
+ _nm_object_ensure_inited (NM_OBJECT (device));
+ return device;
}
/**
@@ -168,19 +172,12 @@ register_properties (NMDeviceInfiniband *device)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
NMDeviceInfinibandPrivate *priv;
- object = G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_device_infiniband_parent_class)->constructed (object);
priv = NM_DEVICE_INFINIBAND_GET_PRIVATE (object);
@@ -190,8 +187,6 @@ constructor (GType type,
NM_DBUS_INTERFACE_DEVICE_INFINIBAND);
register_properties (NM_DEVICE_INFINIBAND (object));
-
- return object;
}
static void
@@ -247,7 +242,7 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *eth_class)
g_type_class_add_private (eth_class, sizeof (NMDeviceInfinibandPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->dispose = dispose;
object_class->finalize = finalize;
object_class->get_property = get_property;
diff --git a/libnm-glib/nm-device-modem.c b/libnm-glib/nm-device-modem.c
index e6dc5a2..dd43d3d 100644
--- a/libnm-glib/nm-device-modem.c
+++ b/libnm-glib/nm-device-modem.c
@@ -147,29 +147,21 @@ register_properties (NMDeviceModem *device)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
NMDeviceModemPrivate *priv;
- object = G_OBJECT_CLASS (nm_device_modem_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (object) {
- priv = NM_DEVICE_MODEM_GET_PRIVATE (object);
+ G_OBJECT_CLASS (nm_device_modem_parent_class)->constructed (object);
- priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
- NM_DBUS_SERVICE,
- nm_object_get_path (NM_OBJECT (object)),
- NM_DBUS_INTERFACE_DEVICE_MODEM);
+ priv = NM_DEVICE_MODEM_GET_PRIVATE (object);
- register_properties (NM_DEVICE_MODEM (object));
- }
+ priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
+ NM_DBUS_SERVICE,
+ nm_object_get_path (NM_OBJECT (object)),
+ NM_DBUS_INTERFACE_DEVICE_MODEM);
- return object;
+ register_properties (NM_DEVICE_MODEM (object));
}
static void
@@ -224,7 +216,7 @@ nm_device_modem_class_init (NMDeviceModemClass *modem_class)
g_type_class_add_private (modem_class, sizeof (NMDeviceModemPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->dispose = dispose;
device_class->connection_valid = connection_valid;
diff --git a/libnm-glib/nm-device-wifi.c b/libnm-glib/nm-device-wifi.c
index 4c9c6be..7fca0bc 100644
--- a/libnm-glib/nm-device-wifi.c
+++ b/libnm-glib/nm-device-wifi.c
@@ -97,13 +97,17 @@ static guint signals[LAST_SIGNAL] = { 0 };
GObject *
nm_device_wifi_new (DBusGConnection *connection, const char *path)
{
+ GObject *device;
+
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
- return g_object_new (NM_TYPE_DEVICE_WIFI,
- NM_OBJECT_DBUS_CONNECTION, connection,
- NM_OBJECT_DBUS_PATH, path,
- NULL);
+ device = g_object_new (NM_TYPE_DEVICE_WIFI,
+ NM_OBJECT_DBUS_CONNECTION, connection,
+ NM_OBJECT_DBUS_PATH, path,
+ NULL);
+ _nm_object_ensure_inited (NM_OBJECT (device));
+ return device;
}
/**
@@ -538,19 +542,12 @@ register_properties (NMDeviceWifi *device)
access_point_removed);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
NMDeviceWifiPrivate *priv;
- object = G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object);
priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
@@ -565,15 +562,6 @@ constructor (GType type,
"notify::" NM_DEVICE_STATE,
G_CALLBACK (state_changed_cb),
NULL);
-
- /* Get initial access points to prevent possible errors on
- * AccessPointRemoved signal processing. We could make D-Bus
- * GetAccessPoints() call on a removed WiFi device object (when
- * AccessPointRemoved was triggered by removing the device).
- */
- nm_device_wifi_get_access_points (NM_DEVICE_WIFI (object));
-
- return object;
}
static void
@@ -614,7 +602,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *wifi_class)
g_type_class_add_private (wifi_class, sizeof (NMDeviceWifiPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
diff --git a/libnm-glib/nm-device-wimax.c b/libnm-glib/nm-device-wimax.c
index 2eb8846..e5525a4 100644
--- a/libnm-glib/nm-device-wimax.c
+++ b/libnm-glib/nm-device-wimax.c
@@ -97,13 +97,17 @@ static guint signals[LAST_SIGNAL] = { 0 };
GObject *
nm_device_wimax_new (DBusGConnection *connection, const char *path)
{
+ GObject *device;
+
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
- return g_object_new (NM_TYPE_DEVICE_WIMAX,
- NM_OBJECT_DBUS_CONNECTION, connection,
- NM_OBJECT_DBUS_PATH, path,
- NULL);
+ device = g_object_new (NM_TYPE_DEVICE_WIMAX,
+ NM_OBJECT_DBUS_CONNECTION, connection,
+ NM_OBJECT_DBUS_PATH, path,
+ NULL);
+ _nm_object_ensure_inited (NM_OBJECT (device));
+ return device;
}
/**
@@ -525,19 +529,12 @@ register_properties (NMDeviceWimax *wimax)
nsp_removed);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
NMDeviceWimaxPrivate *priv;
- object = G_OBJECT_CLASS (nm_device_wimax_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_device_wimax_parent_class)->constructed (object);
priv = NM_DEVICE_WIMAX_GET_PRIVATE (object);
@@ -552,8 +549,6 @@ constructor (GType type,
"notify::" NM_DEVICE_STATE,
G_CALLBACK (state_changed_cb),
NULL);
-
- return object;
}
static void
@@ -586,7 +581,7 @@ nm_device_wimax_class_init (NMDeviceWimaxClass *wimax_class)
g_type_class_add_private (wimax_class, sizeof (NMDeviceWimaxPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->dispose = dispose;
device_class->connection_valid = connection_valid;
diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
index 616f110..2a1e58f 100644
--- a/libnm-glib/nm-device.c
+++ b/libnm-glib/nm-device.c
@@ -163,83 +163,21 @@ device_state_changed (DBusGProxy *proxy,
}
static void
-get_all_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
+constructed (GObject *object)
{
- NMObject *self = NM_OBJECT (user_data);
- GHashTable *props = NULL;
- GError *error = NULL;
-
- if (!dbus_g_proxy_end_call (proxy, call, &error,
- DBUS_TYPE_G_MAP_OF_VARIANT, &props,
- G_TYPE_INVALID)) {
- if (!(error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NO_REPLY)) {
- g_warning ("%s: couldn't retrieve device properties: (%d) %s.",
- __func__,
- error ? error->code : -1,
- (error && error->message) ? error->message : "(unknown)");
- }
- g_clear_error (&error);
- g_object_unref (proxy);
- return;
- }
- g_object_unref (proxy);
-
- _nm_object_process_properties_changed (NM_OBJECT (self), props);
- g_hash_table_destroy (props);
-
-}
-
-static void
-initialize_properties (NMObject *object)
-{
- DBusGProxy *props_proxy;
-
- /* D-Bus properties proxy */
- props_proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
- NM_DBUS_SERVICE,
- nm_object_get_path (object),
- "org.freedesktop.DBus.Properties");
- g_assert (props_proxy);
-
- /* Get properties */
- dbus_g_proxy_begin_call (props_proxy, "GetAll",
- get_all_cb,
- object,
- NULL,
- G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
- G_TYPE_INVALID);
-
-}
-
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
-{
- NMObject *object;
NMDevicePrivate *priv;
- object = (NMObject *) G_OBJECT_CLASS (nm_device_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
priv = NM_DEVICE_GET_PRIVATE (object);
- priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+ priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE_DEVICE);
register_properties (NM_DEVICE (object));
- /* Get initial properties, so that we have all properties set even if
- * no PropertiesChanged signal is received.
- * It has to be called after register_for_property_changed().
- */
- initialize_properties (object);
-
dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT_UINT,
G_TYPE_NONE,
G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
@@ -254,8 +192,6 @@ constructor (GType type,
G_CALLBACK (device_state_changed),
NM_DEVICE (object),
NULL);
-
- return G_OBJECT (object);
}
static void
@@ -393,7 +329,7 @@ nm_device_class_init (NMDeviceClass *device_class)
g_type_class_add_private (device_class, sizeof (NMDevicePrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->dispose = dispose;
@@ -704,6 +640,7 @@ GObject *
nm_device_new (DBusGConnection *connection, const char *path)
{
GType dtype;
+ NMDevice *device = NULL;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (path != NULL, NULL);
@@ -712,10 +649,12 @@ nm_device_new (DBusGConnection *connection, const char *path)
if (dtype == G_TYPE_INVALID)
return NULL;
- return g_object_new (dtype,
- NM_OBJECT_DBUS_CONNECTION, connection,
- NM_OBJECT_DBUS_PATH, path,
- NULL);
+ device = (NMDevice *) g_object_new (dtype,
+ NM_OBJECT_DBUS_CONNECTION, connection,
+ NM_OBJECT_DBUS_PATH, path,
+ NULL);
+ _nm_object_ensure_inited (NM_OBJECT (device));
+ return G_OBJECT (device);
}
typedef struct {
diff --git a/libnm-glib/nm-dhcp4-config.c b/libnm-glib/nm-dhcp4-config.c
index 06c292d..2074e6d 100644
--- a/libnm-glib/nm-dhcp4-config.c
+++ b/libnm-glib/nm-dhcp4-config.c
@@ -90,34 +90,25 @@ register_properties (NMDHCP4Config *config)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- NMObject *object;
DBusGConnection *connection;
NMDHCP4ConfigPrivate *priv;
- object = (NMObject *) G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_dhcp4_config_parent_class)->constructed (object);
priv = NM_DHCP4_CONFIG_GET_PRIVATE (object);
priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- connection = nm_object_get_connection (object);
+ connection = nm_object_get_connection (NM_OBJECT (object));
priv->proxy = dbus_g_proxy_new_for_name (connection,
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE_DHCP4_CONFIG);
register_properties (NM_DHCP4_CONFIG (object));
-
- return G_OBJECT (object);
}
static void
@@ -159,7 +150,7 @@ nm_dhcp4_config_class_init (NMDHCP4ConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMDHCP4ConfigPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->finalize = finalize;
diff --git a/libnm-glib/nm-dhcp6-config.c b/libnm-glib/nm-dhcp6-config.c
index 84eb88f..3764cbf 100644
--- a/libnm-glib/nm-dhcp6-config.c
+++ b/libnm-glib/nm-dhcp6-config.c
@@ -90,34 +90,25 @@ register_properties (NMDHCP6Config *config)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- NMObject *object;
DBusGConnection *connection;
NMDHCP6ConfigPrivate *priv;
- object = (NMObject *) G_OBJECT_CLASS (nm_dhcp6_config_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_dhcp6_config_parent_class)->constructed (object);
priv = NM_DHCP6_CONFIG_GET_PRIVATE (object);
priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- connection = nm_object_get_connection (object);
+ connection = nm_object_get_connection (NM_OBJECT (object));
priv->proxy = dbus_g_proxy_new_for_name (connection,
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE_DHCP6_CONFIG);
register_properties (NM_DHCP6_CONFIG (object));
-
- return G_OBJECT (object);
}
static void
@@ -159,7 +150,7 @@ nm_dhcp6_config_class_init (NMDHCP6ConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMDHCP6ConfigPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->finalize = finalize;
diff --git a/libnm-glib/nm-ip4-config.c b/libnm-glib/nm-ip4-config.c
index 3ea5db0..5667854 100644
--- a/libnm-glib/nm-ip4-config.c
+++ b/libnm-glib/nm-ip4-config.c
@@ -132,32 +132,23 @@ register_properties (NMIP4Config *config)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- NMObject *object;
DBusGConnection *connection;
NMIP4ConfigPrivate *priv;
- object = (NMObject *) G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_ip4_config_parent_class)->constructed (object);
priv = NM_IP4_CONFIG_GET_PRIVATE (object);
- connection = nm_object_get_connection (object);
+ connection = nm_object_get_connection (NM_OBJECT (object));
priv->proxy = dbus_g_proxy_new_for_name (connection,
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE_IP4_CONFIG);
register_properties (NM_IP4_CONFIG (object));
-
- return G_OBJECT (object);
}
static void
@@ -226,7 +217,7 @@ nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->finalize = finalize;
diff --git a/libnm-glib/nm-ip6-config.c b/libnm-glib/nm-ip6-config.c
index 0184226..c9a2627 100644
--- a/libnm-glib/nm-ip6-config.c
+++ b/libnm-glib/nm-ip6-config.c
@@ -216,20 +216,13 @@ nm_ip6_config_get_routes (NMIP6Config *config)
return NM_IP6_CONFIG_GET_PRIVATE (config)->routes;
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
DBusGConnection *connection;
NMIP6ConfigPrivate *priv;
- object = G_OBJECT_CLASS (nm_ip6_config_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_ip6_config_parent_class)->constructed (object);
priv = NM_IP6_CONFIG_GET_PRIVATE (object);
connection = nm_object_get_connection (NM_OBJECT (object));
@@ -240,8 +233,6 @@ constructor (GType type,
NM_DBUS_INTERFACE_IP6_CONFIG);
register_properties (NM_IP6_CONFIG (object));
-
- return object;
}
static void
@@ -309,7 +300,7 @@ nm_ip6_config_class_init (NMIP6ConfigClass *config_class)
g_type_class_add_private (config_class, sizeof (NMIP6ConfigPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->finalize = finalize;
diff --git a/libnm-glib/nm-object-private.h b/libnm-glib/nm-object-private.h
index 83cd82f..9e7bbe5 100644
--- a/libnm-glib/nm-object-private.h
+++ b/libnm-glib/nm-object-private.h
@@ -23,8 +23,7 @@
#ifndef NM_OBJECT_PRIVATE_H
#define NM_OBJECT_PRIVATE_H
-#include <glib.h>
-#include <glib-object.h>
+#include <gio/gio.h>
#include "nm-object.h"
void _nm_object_ensure_inited (NMObject *object);
@@ -47,7 +46,12 @@ void _nm_object_register_properties (NMObject *object,
gboolean _nm_object_reload_properties (NMObject *object, GError **error);
-void _nm_object_process_properties_changed (NMObject *self, GHashTable *properties);
+void _nm_object_reload_properties_async (NMObject *object,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean _nm_object_reload_properties_finish (NMObject *object,
+ GAsyncResult *result,
+ GError **error);
typedef void (*NMPseudoPropertyChangedFunc) (NMObject *self, NMObject *changed);
void _nm_object_register_pseudo_property (NMObject *object,
diff --git a/libnm-glib/nm-object.c b/libnm-glib/nm-object.c
index 58efe06..4f87b37 100644
--- a/libnm-glib/nm-object.c
+++ b/libnm-glib/nm-object.c
@@ -34,7 +34,13 @@
#define DEBUG 0
-G_DEFINE_ABSTRACT_TYPE (NMObject, nm_object, G_TYPE_OBJECT)
+static void nm_object_initable_iface_init (GInitableIface *iface);
+static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init);
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init);
+ )
#define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate))
@@ -47,6 +53,8 @@ typedef struct {
gpointer field;
} PropertyInfo;
+static void reload_complete (NMObject *object);
+
typedef struct {
PropertyInfo pi;
@@ -70,6 +78,10 @@ typedef struct {
GSList *notify_props;
guint32 notify_id;
gboolean inited, disposed;
+
+ GSList *reload_results;
+ guint reload_remaining;
+ GError *reload_error;
} NMObjectPrivate;
enum {
@@ -96,8 +108,6 @@ constructor (GType type,
object = G_OBJECT_CLASS (nm_object_parent_class)->constructor (type,
n_construct_params,
construct_params);
- if (!object)
- return NULL;
priv = NM_OBJECT_GET_PRIVATE (object);
@@ -107,17 +117,78 @@ constructor (GType type,
return NULL;
}
- priv->properties_proxy = dbus_g_proxy_new_for_name (priv->connection,
- NM_DBUS_SERVICE,
- priv->path,
- "org.freedesktop.DBus.Properties");
-
_nm_object_cache_add (NM_OBJECT (object));
return object;
}
static void
+constructed (GObject *object)
+{
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+
+ if (G_OBJECT_CLASS (nm_object_parent_class)->constructed)
+ G_OBJECT_CLASS (nm_object_parent_class)->constructed (object);
+
+ priv->properties_proxy = dbus_g_proxy_new_for_name (priv->connection,
+ NM_DBUS_SERVICE,
+ priv->path,
+ "org.freedesktop.DBus.Properties");
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (initable);
+
+ priv->inited = TRUE;
+ return _nm_object_reload_properties (NM_OBJECT (initable), error);
+}
+
+static void
+init_async_got_properties (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+ GSimpleAsyncResult *simple = user_data;
+ GError *error = NULL;
+
+ priv->inited = TRUE;
+ if (_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error))
+ g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+ else
+ g_simple_async_result_take_error (simple, error);
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+ GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (G_OBJECT (initable), callback, user_data, init_async);
+ _nm_object_reload_properties_async (NM_OBJECT (initable), init_async_got_properties, simple);
+}
+
+static gboolean
+init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* This is needed for now because of bug 667375; it can go away
+ * when we depend on glib >= 2.38
+ */
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+ else
+ return g_simple_async_result_get_op_res_gboolean (simple);
+}
+
+static void
dispose (GObject *object)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
@@ -219,6 +290,7 @@ nm_object_class_init (NMObjectClass *nm_object_class)
/* virtual methods */
object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
@@ -253,6 +325,19 @@ nm_object_class_init (NMObjectClass *nm_object_class)
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
+static void
+nm_object_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = init_sync;
+}
+
+static void
+nm_object_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+ iface->init_async = init_async;
+ iface->init_finish = init_finish;
+}
+
/**
* nm_object_get_connection:
* @object: a #NMObject
@@ -352,15 +437,25 @@ static GObject *
_nm_object_create (GType type, DBusGConnection *connection, const char *path)
{
NMObjectTypeFunc type_func;
+ GObject *object;
+ GError *error = NULL;
type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
if (type_func)
type = type_func (connection, path);
- return g_object_new (type,
- NM_OBJECT_DBUS_CONNECTION, connection,
- NM_OBJECT_DBUS_PATH, path,
- NULL);
+ object = g_object_new (type,
+ NM_OBJECT_DBUS_CONNECTION, connection,
+ NM_OBJECT_DBUS_PATH, path,
+ NULL);
+ if (!g_initable_init (G_INITABLE (object), NULL, &error)) {
+ g_object_unref (object);
+ object = NULL;
+ g_warning ("Could not create object for %s: %s", path, error->message);
+ g_error_free (error);
+ }
+
+ return object;
}
typedef void (*NMObjectCreateCallbackFunc) (GObject *, gpointer);
@@ -372,6 +467,33 @@ typedef struct {
} NMObjectTypeAsyncData;
static void
+create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data)
+{
+ async_data->callback (object, async_data->user_data);
+
+ g_free (async_data->path);
+ g_slice_free (NMObjectTypeAsyncData, async_data);
+}
+
+static void
+async_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ NMObjectTypeAsyncData *async_data = user_data;
+ GObject *object = G_OBJECT (source);
+ GError *error = NULL;
+
+ if (!g_async_initable_init_finish (G_ASYNC_INITABLE (object), result, &error)) {
+ g_warning ("Could not create object for %s: %s",
+ nm_object_get_path (NM_OBJECT (object)), error->message);
+ g_error_free (error);
+ g_object_unref (object);
+ object = NULL;
+ }
+
+ create_async_complete (object, async_data);
+}
+
+static void
async_got_type (GType type, gpointer user_data)
{
NMObjectTypeAsyncData *async_data = user_data;
@@ -382,13 +504,13 @@ async_got_type (GType type, gpointer user_data)
NM_OBJECT_DBUS_CONNECTION, async_data->connection,
NM_OBJECT_DBUS_PATH, async_data->path,
NULL);
- } else
- object = NULL;
-
- async_data->callback (object, async_data->user_data);
+ } else {
+ create_async_complete (NULL, async_data);
+ return;
+ }
- g_free (async_data->path);
- g_slice_free (NMObjectTypeAsyncData, async_data);
+ g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT,
+ NULL, async_inited, async_data);
}
static void
@@ -396,6 +518,7 @@ _nm_object_create_async (GType type, DBusGConnection *connection, const char *pa
NMObjectCreateCallbackFunc callback, gpointer user_data)
{
NMObjectTypeAsyncFunc type_async_func;
+ NMObjectTypeFunc type_func;
NMObjectTypeAsyncData *async_data;
async_data = g_slice_new (NMObjectTypeAsyncData);
@@ -405,10 +528,16 @@ _nm_object_create_async (GType type, DBusGConnection *connection, const char *pa
async_data->user_data = user_data;
type_async_func = g_hash_table_lookup (type_async_funcs, GSIZE_TO_POINTER (type));
- if (type_async_func)
+ if (type_async_func) {
type_async_func (connection, path, async_got_type, async_data);
- else
- async_got_type (type, async_data);
+ return;
+ }
+
+ type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
+ if (type_func)
+ type = type_func (connection, path);
+
+ async_got_type (type, async_data);
}
/* Stolen from dbus-glib */
@@ -449,6 +578,7 @@ object_created (GObject *obj, gpointer user_data)
{
ObjectCreatedData *odata = user_data;
NMObject *self = odata->self;
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
PropertyInfo *pi = odata->pi;
/* We assume that on error, the creator_func printed something */
@@ -478,6 +608,9 @@ object_created (GObject *obj, gpointer user_data)
if (odata->property_name)
_nm_object_queue_notify (self, odata->property_name);
+ if (priv->reload_results && --priv->reload_remaining == 0)
+ reload_complete (self);
+
g_object_unref (self);
g_free (odata->objects);
g_slice_free (ObjectCreatedData, odata);
@@ -514,12 +647,14 @@ handle_object_property (NMObject *self, const char *property_name, GValue *value
obj = _nm_object_create (pi->object_type, priv->connection, path);
object_created (obj, odata);
return obj != NULL;
- } else {
- _nm_object_create_async (pi->object_type, priv->connection, path,
- object_created, odata);
- /* Assume success */
- return TRUE;
}
+
+ if (priv->reload_results)
+ priv->reload_remaining++;
+ _nm_object_create_async (pi->object_type, priv->connection, path,
+ object_created, odata);
+ /* Assume success */
+ return TRUE;
}
static gboolean
@@ -532,6 +667,7 @@ handle_object_array_property (NMObject *self, const char *property_name, GValue
GPtrArray **array = pi->field;
const char *path;
ObjectCreatedData *odata;
+ gboolean add_to_reload = (priv->reload_results != NULL);
int i;
paths = g_value_get_boxed (value);
@@ -554,13 +690,19 @@ handle_object_array_property (NMObject *self, const char *property_name, GValue
obj = G_OBJECT (_nm_object_cache_get (path));
if (obj) {
object_created (obj, odata);
+ continue;
} else if (synchronously) {
obj = _nm_object_create (pi->object_type, priv->connection, path);
object_created (obj, odata);
- } else {
- _nm_object_create_async (pi->object_type, priv->connection, path,
- object_created, odata);
+ continue;
}
+
+ if (add_to_reload) {
+ priv->reload_remaining++;
+ add_to_reload = FALSE;
+ }
+ _nm_object_create_async (pi->object_type, priv->connection, path,
+ object_created, odata);
}
if (!synchronously) {
@@ -636,8 +778,8 @@ out:
g_free (prop_name);
}
-void
-_nm_object_process_properties_changed (NMObject *self, GHashTable *properties)
+static void
+process_properties_changed (NMObject *self, GHashTable *properties)
{
GHashTableIter iter;
gpointer name, value;
@@ -652,7 +794,7 @@ properties_changed_proxy (DBusGProxy *proxy,
GHashTable *properties,
gpointer user_data)
{
- _nm_object_process_properties_changed (NM_OBJECT (user_data), properties);
+ process_properties_changed (NM_OBJECT (user_data), properties);
}
#define HANDLE_TYPE(ucase, lcase, getter) \
@@ -773,8 +915,6 @@ _nm_object_reload_properties (NMObject *object, GError **error)
if (!priv->property_interfaces)
return TRUE;
- priv->inited = TRUE;
-
for (p = priv->property_interfaces; p; p = p->next) {
if (!dbus_g_proxy_call (priv->properties_proxy, "GetAll", error,
G_TYPE_STRING, p->data,
@@ -783,7 +923,7 @@ _nm_object_reload_properties (NMObject *object, GError **error)
G_TYPE_INVALID))
return FALSE;
- _nm_object_process_properties_changed (object, props);
+ process_properties_changed (object, props);
g_hash_table_destroy (props);
}
@@ -803,11 +943,14 @@ _nm_object_ensure_inited (NMObject *object)
GError *error = NULL;
if (!priv->inited) {
- if (!_nm_object_reload_properties (object, &error)) {
+ if (!g_initable_init (G_INITABLE (object), NULL, &error)) {
g_warning ("Could not initialize %s %s: %s",
G_OBJECT_TYPE_NAME (object), priv->path,
error->message);
g_error_free (error);
+
+ /* Only warn once */
+ priv->inited = TRUE;
}
}
}
@@ -1026,3 +1169,148 @@ _nm_object_reload_pseudo_property (NMObject *object,
handle_object_array_property (object, NULL, &value, &ppi->pi, TRUE);
g_value_unset (&value);
}
+
+static void
+reload_complete (NMObject *object)
+{
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+ GSimpleAsyncResult *simple;
+ GSList *results, *iter;
+ GError *error;
+
+ results = priv->reload_results;
+ priv->reload_results = NULL;
+ error = priv->reload_error;
+ priv->reload_error = NULL;
+
+ for (iter = results; iter; iter = iter->next) {
+ simple = results->data;
+
+ if (error)
+ g_simple_async_result_set_from_error (simple, error);
+ else
+ g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ }
+ g_slist_free (results);
+ g_clear_error (&error);
+}
+
+static void
+reload_got_properties (DBusGProxy *proxy, DBusGProxyCall *call,
+ gpointer user_data)
+{
+ NMObject *object = user_data;
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+ GHashTable *props = NULL;
+ GError *error = NULL;
+
+ if (dbus_g_proxy_end_call (proxy, call, &error,
+ DBUS_TYPE_G_MAP_OF_VARIANT, &props,
+ G_TYPE_INVALID)) {
+ process_properties_changed (object, props);
+ g_hash_table_destroy (props);
+ } else {
+ if (priv->reload_error)
+ g_error_free (error);
+ else
+ priv->reload_error = error;
+ }
+
+ if (--priv->reload_remaining == 0)
+ reload_complete (object);
+}
+
+static void
+reload_got_pseudo_property (DBusGProxy *proxy, DBusGProxyCall *call,
+ gpointer user_data)
+{
+ PseudoPropertyInfo *ppi = user_data;
+ NMObject *object = ppi->self;
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+ GPtrArray *temp;
+ GValue value = { 0, };
+ GError *error = NULL;
+
+ if (dbus_g_proxy_end_call (proxy, call, &error,
+ DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, &temp,
+ G_TYPE_INVALID)) {
+ g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
+ g_value_take_boxed (&value, temp);
+ handle_object_array_property (object, NULL, &value, &ppi->pi, FALSE);
+ g_value_unset (&value);
+ } else {
+ if (priv->reload_error)
+ g_error_free (error);
+ else
+ priv->reload_error = error;
+ }
+
+ if (--priv->reload_remaining == 0)
+ reload_complete (object);
+}
+
+void
+_nm_object_reload_properties_async (NMObject *object, GAsyncReadyCallback callback, gpointer user_data)
+{
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+ GSimpleAsyncResult *simple;
+ GSList *p;
+
+ simple = g_simple_async_result_new (G_OBJECT (object), callback,
+ user_data, _nm_object_reload_properties_async);
+
+ if (!priv->property_interfaces && !priv->pseudo_properties) {
+ g_simple_async_result_complete_in_idle (simple);
+ return;
+ }
+
+ priv->reload_results = g_slist_prepend (priv->reload_results, simple);
+
+ /* If there was already a reload happening, we don't need to
+ * re-read the properties again, we just need to wait for the
+ * existing reload to finish.
+ */
+ if (priv->reload_results->next)
+ return;
+
+ for (p = priv->property_interfaces; p; p = p->next) {
+ priv->reload_remaining++;
+ dbus_g_proxy_begin_call (priv->properties_proxy, "GetAll",
+ reload_got_properties, object, NULL,
+ G_TYPE_STRING, p->data,
+ G_TYPE_INVALID);
+ }
+
+ if (priv->pseudo_properties) {
+ GHashTableIter iter;
+ gpointer key, value;
+ PseudoPropertyInfo *ppi;
+
+ g_hash_table_iter_init (&iter, priv->pseudo_properties);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ ppi = value;
+ priv->reload_remaining++;
+ dbus_g_proxy_begin_call (ppi->proxy, ppi->get_method,
+ reload_got_pseudo_property, ppi, NULL,
+ G_TYPE_INVALID);
+ }
+ }
+}
+
+gboolean
+_nm_object_reload_properties_finish (NMObject *object, GAsyncResult *result, GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (NM_IS_OBJECT (object), FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (object), _nm_object_reload_properties_async), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ return g_simple_async_result_get_op_res_gboolean (simple);
+}
diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c
index 91d3d46..d8bcfd9 100644
--- a/libnm-glib/nm-remote-connection.c
+++ b/libnm-glib/nm-remote-connection.c
@@ -382,18 +382,11 @@ nm_remote_connection_new (DBusGConnection *bus,
NULL);
}
-static GObject *
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
NMRemoteConnectionPrivate *priv;
- object = G_OBJECT_CLASS (nm_remote_connection_parent_class)->constructor (type, n_construct_params, construct_params);
- if (!object)
- return NULL;
-
priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object);
g_assert (priv->bus);
g_assert (nm_connection_get_path (NM_CONNECTION (object)));
@@ -414,7 +407,6 @@ constructor (GType type,
dbus_g_proxy_begin_call (priv->proxy, "GetSettings",
init_get_settings_cb, object, NULL,
G_TYPE_INVALID);
- return object;
}
static void
@@ -486,7 +478,7 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
/* Properties */
g_object_class_install_property
diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c
index 60c13c8..19e297c 100644
--- a/libnm-glib/nm-remote-settings.c
+++ b/libnm-glib/nm-remote-settings.c
@@ -754,19 +754,12 @@ nm_remote_settings_init (NMRemoteSettings *self)
priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
}
-static GObject *
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
NMRemoteSettingsPrivate *priv;
GError *error = NULL;
- object = G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type, n_construct_params, construct_params);
- if (!object)
- return NULL;
-
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
/* D-Bus proxy for clearing connections on NameOwnerChanged */
@@ -847,7 +840,6 @@ constructor (GType type,
G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
G_TYPE_INVALID);
- return object;
}
static void
@@ -937,7 +929,7 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class)
g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate));
/* Virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
diff --git a/libnm-glib/nm-vpn-connection.c b/libnm-glib/nm-vpn-connection.c
index 58c2ea4..652206b 100644
--- a/libnm-glib/nm-vpn-connection.c
+++ b/libnm-glib/nm-vpn-connection.c
@@ -164,25 +164,18 @@ register_properties (NMVPNConnection *connection)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- NMObject *object;
NMVPNConnectionPrivate *priv;
- object = (NMObject *) G_OBJECT_CLASS (nm_vpn_connection_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_vpn_connection_parent_class)->constructed (object);
priv = NM_VPN_CONNECTION_GET_PRIVATE (object);
- priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+ priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE_VPN_CONNECTION);
dbus_g_object_register_marshaller (_nm_marshal_VOID__UINT_UINT,
@@ -197,8 +190,6 @@ constructor (GType type,
NULL);
register_properties (NM_VPN_CONNECTION (object));
-
- return G_OBJECT (object);
}
static void
@@ -241,7 +232,7 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class)
g_type_class_add_private (connection_class, sizeof (NMVPNConnectionPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->finalize = finalize;
diff --git a/libnm-glib/nm-wimax-nsp.c b/libnm-glib/nm-wimax-nsp.c
index bfacc87..c3b222d 100644
--- a/libnm-glib/nm-wimax-nsp.c
+++ b/libnm-glib/nm-wimax-nsp.c
@@ -279,30 +279,21 @@ register_properties (NMWimaxNsp *nsp)
property_info);
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- NMObject *object;
NMWimaxNspPrivate *priv;
- object = (NMObject *) G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
+ G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->constructed (object);
priv = NM_WIMAX_NSP_GET_PRIVATE (object);
- priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (object),
+ priv->proxy = dbus_g_proxy_new_for_name (nm_object_get_connection (NM_OBJECT (object)),
NM_DBUS_SERVICE,
- nm_object_get_path (object),
+ nm_object_get_path (NM_OBJECT (object)),
NM_DBUS_INTERFACE_WIMAX_NSP);
register_properties (NM_WIMAX_NSP (object));
-
- return G_OBJECT (object);
}
@@ -314,7 +305,7 @@ nm_wimax_nsp_class_init (NMWimaxNspClass *nsp_class)
g_type_class_add_private (nsp_class, sizeof (NMWimaxNspPrivate));
/* virtual methods */
- object_class->constructor = constructor;
+ object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
--
1.7.7.5
>From cf5ce90030f7b9a2e14a860f90d9fce2717f198c Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Sat, 21 Jan 2012 08:02:24 -0500
Subject: [PATCH 11/12] libnm-glib: nm_client_new_async, fix up NMClient
asynchrony issues
---
libnm-glib/Makefile.am | 4 +-
libnm-glib/libnm-glib.ver | 2 +
libnm-glib/nm-client.c | 201 ++++++++++++++++++++--------------------
libnm-glib/nm-client.h | 7 ++
libnm-glib/nm-object-private.h | 2 +
libnm-glib/nm-object.c | 23 ++++-
6 files changed, 134 insertions(+), 105 deletions(-)
diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am
index 7bf4fef..6be78e1 100644
--- a/libnm-glib/Makefile.am
+++ b/libnm-glib/Makefile.am
@@ -188,8 +188,8 @@ if HAVE_INTROSPECTION
introspection_sources = $(libnminclude_HEADERS) $(libnm_glib_la_csources)
NMClient-1.0.gir: libnm-glib.la
-NMClient_1_0_gir_INCLUDES = GObject-2.0 DBusGLib-1.0
-NMClient_1_0_gir_PACKAGES = gobject-2.0 dbus-glib-1 gudev-1.0
+NMClient_1_0_gir_INCLUDES = Gio-2.0 DBusGLib-1.0
+NMClient_1_0_gir_PACKAGES = gio-2.0 dbus-glib-1 gudev-1.0
NMClient_1_0_gir_CFLAGS = $(INCLUDES) -I$(top_srcdir)/libnm-glib -I$(top_srcdir)/libnm-util
NMClient_1_0_gir_LIBS = libnm-glib.la
NMClient_1_0_gir_FILES = $(introspection_sources)
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
index 77bcd05..c5b8741 100644
--- a/libnm-glib/libnm-glib.ver
+++ b/libnm-glib/libnm-glib.ver
@@ -44,6 +44,8 @@ global:
nm_client_networking_get_enabled;
nm_client_networking_set_enabled;
nm_client_new;
+ nm_client_new_async;
+ nm_client_new_finish;
nm_client_sleep;
nm_client_wimax_get_enabled;
nm_client_wimax_hardware_get_enabled;
diff --git a/libnm-glib/nm-client.c b/libnm-glib/nm-client.c
index f27521d..fe2663a 100644
--- a/libnm-glib/nm-client.c
+++ b/libnm-glib/nm-client.c
@@ -142,108 +142,12 @@ poke_wireless_devices_with_rf_status (NMClient *client)
}
static void
-update_wireless_status (NMClient *client, gboolean notify)
-{
- NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
- gboolean oldval;
- gboolean poke = FALSE;
-
- oldval = priv->wireless_hw_enabled;
- _nm_object_reload_property (NM_OBJECT (client),
- NM_DBUS_INTERFACE,
- "WirelessHardwareEnabled");
- if (oldval != priv->wireless_hw_enabled) {
- poke = TRUE;
- if (notify)
- _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIRELESS_HARDWARE_ENABLED);
- }
-
- oldval = priv->wireless_enabled;
- if (priv->wireless_hw_enabled == FALSE) {
- priv->wireless_enabled = FALSE;
- } else {
- _nm_object_reload_property (NM_OBJECT (client),
- NM_DBUS_INTERFACE,
- "WirelessEnabled");
- }
-
- if (oldval != priv->wireless_enabled) {
- poke = TRUE;
- if (notify)
- _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIRELESS_ENABLED);
- }
-
- if (poke)
- poke_wireless_devices_with_rf_status (client);
-}
-
-static void
wireless_enabled_cb (GObject *object, GParamSpec *pspec, gpointer user_data)
{
poke_wireless_devices_with_rf_status (NM_CLIENT (object));
}
static void
-update_wwan_status (NMClient *client, gboolean notify)
-{
- NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
- gboolean oldval;
-
- oldval = priv->wwan_hw_enabled;
- _nm_object_reload_property (NM_OBJECT (client),
- NM_DBUS_INTERFACE,
- "WwanHardwareEnabled");
- if (oldval != priv->wwan_hw_enabled) {
- if (notify)
- _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_HARDWARE_ENABLED);
- }
-
- oldval = priv->wwan_enabled;
- if (priv->wwan_hw_enabled == FALSE) {
- priv->wwan_enabled = FALSE;
- } else {
- _nm_object_reload_property (NM_OBJECT (client),
- NM_DBUS_INTERFACE,
- "WwanEnabled");
- }
-
- if (oldval != priv->wwan_enabled) {
- if (notify)
- _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WWAN_ENABLED);
- }
-}
-
-static void
-update_wimax_status (NMClient *client, gboolean notify)
-{
- NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
- gboolean oldval;
-
- oldval = priv->wimax_hw_enabled;
- _nm_object_reload_property (NM_OBJECT (client),
- NM_DBUS_INTERFACE,
- "WimaxHardwareEnabled");
- if (oldval != priv->wimax_hw_enabled) {
- if (notify)
- _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIMAX_HARDWARE_ENABLED);
- }
-
- oldval = priv->wimax_enabled;
- if (priv->wimax_hw_enabled == FALSE) {
- priv->wimax_enabled = FALSE;
- } else {
- _nm_object_reload_property (NM_OBJECT (client),
- NM_DBUS_INTERFACE,
- "WimaxEnabled");
- }
-
- if (oldval != priv->wimax_enabled) {
- if (notify)
- _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_WIMAX_ENABLED);
- }
-}
-
-static void
register_properties (NMClient *client)
{
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client);
@@ -1131,6 +1035,20 @@ free_object_array (GPtrArray **array)
}
static void
+updated_properties (GObject *object, GAsyncResult *result, gpointer user_data)
+{
+ NMClient *client = NM_CLIENT (user_data);
+ GError *error = NULL;
+
+ if (!_nm_object_reload_properties_finish (NM_OBJECT (object), result, &error)) {
+ g_warning ("%s: error reading NMClient properties: %s", __func__, error->message);
+ g_error_free (error);
+ }
+
+ _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
+}
+
+static void
proxy_name_owner_changed (DBusGProxy *proxy,
const char *name,
const char *old_owner,
@@ -1158,6 +1076,7 @@ proxy_name_owner_changed (DBusGProxy *proxy,
if (!priv->manager_running) {
priv->state = NM_STATE_UNKNOWN;
_nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
+ _nm_object_suppress_property_updates (NM_OBJECT (client), TRUE);
poke_wireless_devices_with_rf_status (client);
free_object_array (&priv->devices);
free_object_array (&priv->active_connections);
@@ -1168,10 +1087,8 @@ proxy_name_owner_changed (DBusGProxy *proxy,
priv->wimax_enabled = FALSE;
priv->wimax_hw_enabled = FALSE;
} else {
- _nm_object_queue_notify (NM_OBJECT (client), NM_CLIENT_MANAGER_RUNNING);
- update_wireless_status (client, TRUE);
- update_wwan_status (client, TRUE);
- update_wimax_status (client, TRUE);
+ _nm_object_suppress_property_updates (NM_OBJECT (client), FALSE);
+ _nm_object_reload_properties_async (NM_OBJECT (client), updated_properties, client);
}
}
@@ -1194,6 +1111,10 @@ client_device_removed (NMObject *client, NMObject *device)
*
* Creates a new #NMClient.
*
+ * Note that this will do blocking D-Bus calls to initialize the
+ * client. You can use nm_client_new_async() if you want to avoid
+ * that.
+ *
* Returns: a new #NMClient
**/
NMClient *
@@ -1223,6 +1144,84 @@ nm_client_new (void)
}
static void
+client_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GSimpleAsyncResult *simple = user_data;
+ GError *error = NULL;
+
+ if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source), result, &error))
+ g_simple_async_result_take_error (simple, error);
+ else
+ g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+/**
+ * nm_client_new_async:
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to call when the client is created
+ * @user_data: data for @callback
+ *
+ * Creates a new #NMClient and begins asynchronously initializing it.
+ * @callback will be called when it is done; use
+ * nm_client_new_finish() to get the result.
+ **/
+void
+nm_client_new_async (GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ DBusGConnection *connection;
+ GError *err = NULL;
+ NMClient *client;
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (NULL, callback, user_data, nm_client_new_async);
+
+#ifdef LIBNM_GLIB_TEST
+ connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
+#else
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
+#endif
+ if (!connection) {
+ g_simple_async_result_take_error (simple, err);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ client = g_object_new (NM_TYPE_CLIENT,
+ NM_OBJECT_DBUS_CONNECTION, connection,
+ NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
+ NULL);
+ g_async_initable_init_async (G_ASYNC_INITABLE (client), G_PRIORITY_DEFAULT,
+ cancellable, client_inited, simple);
+}
+
+/**
+ * nm_client_new_finish:
+ * @result: a #GAsyncResult
+ * @error: location for a #GError, or %NULL
+ *
+ * Gets the result of an nm_client_new_async() call.
+ *
+ * Returns: a new #NMClient, or %NULL on error
+ **/
+NMClient *
+nm_client_new_finish (GAsyncResult *result, GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_client_new_async), NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+ else
+ return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
+}
+
+static void
constructed (GObject *object)
{
DBusGConnection *connection;
@@ -1356,7 +1355,6 @@ init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
}
if (!priv->manager_running) {
- g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
init_async_complete (init_data);
return;
}
@@ -1384,6 +1382,7 @@ init_async (GAsyncInitable *initable, int io_priority,
init_data->client = NM_CLIENT (initable);
init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
user_data, init_async);
+ g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
/* Check if NM is running */
dbus_g_proxy_begin_call (priv->bus_proxy, "NameHasOwner",
diff --git a/libnm-glib/nm-client.h b/libnm-glib/nm-client.h
index 44f1d2b..684326f 100644
--- a/libnm-glib/nm-client.h
+++ b/libnm-glib/nm-client.h
@@ -26,6 +26,7 @@
#include <glib.h>
#include <glib-object.h>
+#include <gio/gio.h>
#include <dbus/dbus-glib.h>
#include <NetworkManager.h>
#include "nm-object.h"
@@ -106,6 +107,12 @@ GType nm_client_get_type (void);
NMClient *nm_client_new (void);
+void nm_client_new_async (GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+NMClient *nm_client_new_finish (GAsyncResult *result,
+ GError **error);
+
const GPtrArray *nm_client_get_devices (NMClient *client);
NMDevice *nm_client_get_device_by_path (NMClient *client, const char *object_path);
NMDevice *nm_client_get_device_by_iface (NMClient *client, const char *iface);
diff --git a/libnm-glib/nm-object-private.h b/libnm-glib/nm-object-private.h
index 9e7bbe5..7ec2162 100644
--- a/libnm-glib/nm-object-private.h
+++ b/libnm-glib/nm-object-private.h
@@ -66,6 +66,8 @@ void _nm_object_reload_pseudo_property (NMObject *object,
void _nm_object_queue_notify (NMObject *object, const char *property);
+void _nm_object_suppress_property_updates (NMObject *object, gboolean suppress);
+
/* DBus property accessors */
void _nm_object_reload_property (NMObject *object,
diff --git a/libnm-glib/nm-object.c b/libnm-glib/nm-object.c
index 4f87b37..d76129d 100644
--- a/libnm-glib/nm-object.c
+++ b/libnm-glib/nm-object.c
@@ -74,6 +74,7 @@ typedef struct {
GSList *property_tables;
GHashTable *pseudo_properties;
NMObject *parent;
+ gboolean suppress_property_updates;
GSList *notify_props;
guint32 notify_id;
@@ -781,9 +782,13 @@ out:
static void
process_properties_changed (NMObject *self, GHashTable *properties)
{
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
GHashTableIter iter;
gpointer name, value;
+ if (priv->suppress_property_updates)
+ return;
+
g_hash_table_iter_init (&iter, properties);
while (g_hash_table_iter_next (&iter, &name, &value))
handle_property_changed (self, name, value, FALSE);
@@ -937,6 +942,15 @@ _nm_object_reload_properties (NMObject *object, GError **error)
}
void
+_nm_object_suppress_property_updates (NMObject *object, gboolean suppress)
+{
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
+
+ priv->suppress_property_updates = suppress;
+}
+
+
+void
_nm_object_ensure_inited (NMObject *object)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
@@ -1039,6 +1053,9 @@ pseudo_property_added (DBusGProxy *proxy, const char *path, gpointer user_data)
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (ppi->self);
NMObject *obj;
+ if (priv->suppress_property_updates)
+ return;
+
obj = _nm_object_cache_get (path);
if (obj)
pseudo_property_object_created (G_OBJECT (obj), ppi);
@@ -1052,11 +1069,12 @@ static void
pseudo_property_removed (DBusGProxy *proxy, const char *path, gpointer user_data)
{
PseudoPropertyInfo *ppi = user_data;
+ NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (ppi->self);
GPtrArray *list = *(GPtrArray **)ppi->pi.field;
NMObject *obj = NULL;
int i;
- if (!list)
+ if (!list || priv->suppress_property_updates)
return;
for (i = 0; i < list->len; i++) {
@@ -1239,7 +1257,8 @@ reload_got_pseudo_property (DBusGProxy *proxy, DBusGProxyCall *call,
G_TYPE_INVALID)) {
g_value_init (&value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH);
g_value_take_boxed (&value, temp);
- handle_object_array_property (object, NULL, &value, &ppi->pi, FALSE);
+ if (!priv->suppress_property_updates)
+ handle_object_array_property (object, NULL, &value, &ppi->pi, FALSE);
g_value_unset (&value);
} else {
if (priv->reload_error)
--
1.7.7.5
>From 797c9cc8a5161c53288ceb9283a9a203bebe575b Mon Sep 17 00:00:00 2001
From: Dan Winship <danw gnome org>
Date: Tue, 24 Jan 2012 13:49:59 -0500
Subject: [PATCH 12/12] libnm-glib: asyncify NMRemoteSettings
Add nm_remote_settings_new_async/_finish, and misc other fixes
---
libnm-glib/libnm-glib.ver | 2 +
libnm-glib/nm-remote-connection.c | 151 ++++++++++-------
libnm-glib/nm-remote-settings.c | 327 +++++++++++++++++++++++++++----------
libnm-glib/nm-remote-settings.h | 9 +-
4 files changed, 341 insertions(+), 148 deletions(-)
diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
index c5b8741..5c84df3 100644
--- a/libnm-glib/libnm-glib.ver
+++ b/libnm-glib/libnm-glib.ver
@@ -157,6 +157,8 @@ global:
nm_remote_settings_get_type;
nm_remote_settings_list_connections;
nm_remote_settings_new;
+ nm_remote_settings_new_async;
+ nm_remote_settings_new_finish;
nm_remote_settings_save_hostname;
nm_secret_agent_delete_secrets;
nm_secret_agent_error_get_type;
diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c
index d8bcfd9..be78a09 100644
--- a/libnm-glib/nm-remote-connection.c
+++ b/libnm-glib/nm-remote-connection.c
@@ -22,6 +22,7 @@
*/
#include <string.h>
+#include <gio/gio.h>
#include <NetworkManager.h>
#include <nm-utils.h>
@@ -32,12 +33,17 @@
#define NM_REMOTE_CONNECTION_BUS "bus"
-G_DEFINE_TYPE (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION)
+static void nm_remote_connection_initable_iface_init (GInitableIface *iface);
+static void nm_remote_connection_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_connection_initable_iface_init);
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_connection_async_initable_iface_init);
+ )
enum {
PROP_0,
PROP_BUS,
- PROP_INIT_RESULT,
LAST_PROP
};
@@ -64,7 +70,6 @@ typedef struct {
DBusGProxy *proxy;
GSList *calls;
- NMRemoteConnectionInitResult init_result;
gboolean visible;
gboolean disposed;
} NMRemoteConnectionPrivate;
@@ -268,38 +273,6 @@ replace_settings (NMRemoteConnection *self, GHashTable *new_settings)
}
static void
-init_get_settings_cb (DBusGProxy *proxy,
- DBusGProxyCall *call,
- gpointer user_data)
-{
- NMRemoteConnection *self = user_data;
- NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
- GHashTable *new_settings;
- GError *error = NULL;
-
- dbus_g_proxy_end_call (proxy, call, &error,
- DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &new_settings,
- G_TYPE_INVALID);
- if (error) {
- g_error_free (error);
-
- /* Connection doesn't exist, or isn't visible to this user */
- if (dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied"))
- priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_INVISIBLE;
- else
- priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_ERROR;
-
- g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT);
- } else {
- priv->visible = TRUE;
- replace_settings (self, new_settings);
- g_hash_table_destroy (new_settings);
- priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS;
- g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT);
- }
-}
-
-static void
updated_get_settings_cb (DBusGProxy *proxy,
DBusGProxyCall *call,
gpointer user_data)
@@ -403,10 +376,76 @@ constructed (GObject *object)
dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "Removed", G_CALLBACK (removed_cb), object, NULL);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+ NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (initable);
+ GHashTable *settings;
+
+ if (!dbus_g_proxy_call (priv->proxy, "GetSettings", error,
+ G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
+ G_TYPE_INVALID,
+ DBUS_TYPE_G_MAP_OF_VARIANT, &settings,
+ G_TYPE_INVALID))
+ return FALSE;
+
+ priv->visible = TRUE;
+ replace_settings (NM_REMOTE_CONNECTION (initable), settings);
+ g_hash_table_destroy (settings);
+ return TRUE;
+}
+
+typedef struct {
+ NMRemoteConnection *connection;
+ GSimpleAsyncResult *result;
+} NMRemoteConnectionInitData;
+
+static void
+init_get_settings_cb (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ gpointer user_data)
+{
+ NMRemoteConnectionInitData *init_data = user_data;
+ NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (init_data->connection);
+ GHashTable *settings;
+ GError *error = NULL;
+
+ dbus_g_proxy_end_call (proxy, call, &error,
+ DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, &settings,
+ G_TYPE_INVALID);
+ if (error) {
+ g_simple_async_result_take_error (init_data->result, error);
+ } else {
+ priv->visible = TRUE;
+ replace_settings (init_data->connection, settings);
+ g_hash_table_destroy (settings);
+ g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+ }
+
+ g_simple_async_result_complete (init_data->result);
+ g_slice_free (NMRemoteConnectionInitData, init_data);
+}
+
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+ GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ NMRemoteConnectionInitData *init_data;
+ NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (initable);
+
+
+ init_data = g_slice_new0 (NMRemoteConnectionInitData);
+ init_data->connection = NM_REMOTE_CONNECTION (initable);
+ init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
+ user_data, init_async);
dbus_g_proxy_begin_call (priv->proxy, "GetSettings",
- init_get_settings_cb, object, NULL,
+ init_get_settings_cb, init_data, NULL,
G_TYPE_INVALID);
+
}
static void
@@ -432,23 +471,6 @@ set_property (GObject *object, guint prop_id,
}
static void
-get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- NMRemoteConnection *self = NM_REMOTE_CONNECTION (object);
- NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self);
-
- switch (prop_id) {
- case PROP_INIT_RESULT:
- g_value_set_uint (value, priv->init_result);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
dispose (GObject *object)
{
NMRemoteConnection *self = NM_REMOTE_CONNECTION (object);
@@ -476,7 +498,6 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
/* virtual methods */
object_class->set_property = set_property;
- object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->constructed = constructed;
@@ -489,16 +510,6 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
DBUS_TYPE_G_CONNECTION,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property
- (object_class, PROP_INIT_RESULT,
- g_param_spec_uint (NM_REMOTE_CONNECTION_INIT_RESULT,
- "Initialization result (PRIVATE)",
- "Initialization result (PRIVATE)",
- NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN,
- NM_REMOTE_CONNECTION_INIT_RESULT_ERROR,
- NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN,
- G_PARAM_READABLE));
-
/* Signals */
/**
* NMRemoteConnection::updated:
@@ -541,3 +552,15 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class)
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
}
+
+static void
+nm_remote_connection_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = init_sync;
+}
+
+static void
+nm_remote_connection_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+ iface->init_async = init_async;
+}
diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c
index 19e297c..e8d3386 100644
--- a/libnm-glib/nm-remote-settings.c
+++ b/libnm-glib/nm-remote-settings.c
@@ -30,7 +30,13 @@
#include "nm-remote-settings.h"
#include "nm-remote-connection-private.h"
-G_DEFINE_TYPE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT)
+static void nm_remote_settings_initable_iface_init (GInitableIface *iface);
+static void nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_remote_settings_initable_iface_init);
+ G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_remote_settings_async_initable_iface_init);
+ )
#define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate))
@@ -277,37 +283,20 @@ connection_visible_cb (NMRemoteConnection *remote,
}
static void
-connection_init_result_cb (NMRemoteConnection *remote,
- GParamSpec *pspec,
- gpointer user_data)
+connection_inited (GObject *source, GAsyncResult *result, gpointer user_data)
{
+ NMRemoteConnection *remote = NM_REMOTE_CONNECTION (source);
NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self);
- guint32 init_result = NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN;
AddConnectionInfo *addinfo;
const char *path;
- GError *add_error = NULL;
+ GError *error = NULL;
gboolean remove_from_pending = TRUE;
- /* Disconnect from the init-result signal just to be safe */
- g_signal_handlers_disconnect_matched (remote,
- G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
- 0,
- 0,
- NULL,
- G_CALLBACK (connection_init_result_cb),
- self);
-
path = nm_connection_get_path (NM_CONNECTION (remote));
-
- g_object_get (G_OBJECT (remote),
- NM_REMOTE_CONNECTION_INIT_RESULT, &init_result,
- NULL);
-
addinfo = add_connection_info_find (self, remote);
- switch (init_result) {
- case NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS:
+ if (g_async_initable_init_finish (G_ASYNC_INITABLE (remote), result, &error)) {
/* ref it when adding to ->connections, since removing it from ->pending
* will unref it.
*/
@@ -323,22 +312,20 @@ connection_init_result_cb (NMRemoteConnection *remote,
* its settings and is valid.
*/
g_signal_emit (self, signals[NEW_CONNECTION], 0, remote);
- break;
- case NM_REMOTE_CONNECTION_INIT_RESULT_INVISIBLE:
- remove_from_pending = FALSE;
- /* fall through */
- case NM_REMOTE_CONNECTION_INIT_RESULT_ERROR:
- /* Complete pending AddConnection callbacks */
+ } else {
+ if (dbus_g_error_has_name (error, "org.freedesktop.NetworkManager.Settings.PermissionDenied")) {
+ /* Connection doesn't exist, or isn't visible to this user */
+ remove_from_pending = FALSE;
+ }
+ g_error_free (error);
+
if (addinfo) {
- add_error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
- NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
- "Connection not visible or not available");
- add_connection_info_complete (self, addinfo, add_error);
- g_error_free (add_error);
+ error = g_error_new_literal (NM_REMOTE_SETTINGS_ERROR,
+ NM_REMOTE_SETTINGS_ERROR_CONNECTION_UNAVAILABLE,
+ "Connection not visible or not available");
+ add_connection_info_complete (self, addinfo, error);
+ g_error_free (error);
}
- break;
- default:
- break;
}
if (remove_from_pending)
@@ -376,9 +363,9 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
G_CALLBACK (connection_visible_cb),
self);
- g_signal_connect (connection, "notify::" NM_REMOTE_CONNECTION_INIT_RESULT,
- G_CALLBACK (connection_init_result_cb),
- self);
+ g_async_initable_init_async (G_ASYNC_INITABLE (connection),
+ G_PRIORITY_DEFAULT, NULL,
+ connection_inited, self);
/* Add the connection to the pending table to wait for it to retrieve
* it's settings asynchronously over D-Bus. The connection isn't
@@ -698,53 +685,109 @@ properties_changed_cb (DBusGProxy *proxy,
}
}
-static void
-get_all_cb (DBusGProxy *proxy,
- DBusGProxyCall *call,
- gpointer user_data)
+/****************************************************************/
+
+/**
+ * nm_remote_settings_new:
+ * @bus: (allow-none): a valid and connected D-Bus connection
+ *
+ * Creates a new object representing the remote settings service.
+ *
+ * Note that this will do blocking D-Bus calls to initialize the
+ * settings object. You can use nm_remote_settings_new_async() if you
+ * want to avoid that.
+ *
+ * Returns: the new remote settings object on success, or %NULL on failure
+ **/
+NMRemoteSettings *
+nm_remote_settings_new (DBusGConnection *bus)
{
- NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data);
- GHashTable *props = NULL;
+ NMRemoteSettings *settings;
GError *error = NULL;
- if (!dbus_g_proxy_end_call (proxy, call, &error,
- DBUS_TYPE_G_MAP_OF_VARIANT, &props,
- G_TYPE_INVALID)) {
+ settings = g_object_new (NM_TYPE_REMOTE_SETTINGS,
+ NM_REMOTE_SETTINGS_BUS, bus,
+ NULL);
+ if (!g_initable_init (G_INITABLE (settings), NULL, &error)) {
/* Don't warn when the call times out because the settings service can't
* be activated or whatever.
*/
- if (!(error->domain == DBUS_GERROR && error->code == DBUS_GERROR_NO_REPLY)) {
- g_warning ("%s: couldn't retrieve system settings properties: (%d) %s.",
- __func__,
- error ? error->code : -1,
- (error && error->message) ? error->message : "(unknown)");
+ if (!g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NO_REPLY)) {
+ g_warning ("%s: (NMRemoteSettings) error initializing: %s\n",
+ __func__, error->message);
}
- g_clear_error (&error);
- return;
+ g_error_free (error);
}
- properties_changed_cb (NULL, props, self);
- g_hash_table_destroy (props);
+ return settings;
}
-/****************************************************************/
+static void
+remote_settings_inited (GObject *source, GAsyncResult *result, gpointer user_data)
+{
+ GSimpleAsyncResult *simple = user_data;
+ GError *error = NULL;
+
+ if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source), result, &error))
+ g_simple_async_result_take_error (simple, error);
+ else
+ g_simple_async_result_set_op_res_gpointer (simple, source, g_object_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
/**
- * nm_remote_settings_new:
+ * nm_remote_settings_new_async:
* @bus: (allow-none): a valid and connected D-Bus connection
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to call when the settings object is created
+ * @user_data: data for @callback
*
- * Creates a new object representing the remote settings service.
+ * Creates a new object representing the remote settings service and
+ * begins asynchronously initializing it. @callback will be called
+ * when it is done; use nm_remote_settings_new_finish() to get the
+ * result.
+ **/
+void
+nm_remote_settings_new_async (DBusGConnection *bus, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data)
+{
+ NMRemoteSettings *self;
+ GSimpleAsyncResult *simple;
+
+ simple = g_simple_async_result_new (NULL, callback, user_data, nm_remote_settings_new_async);
+
+ self = g_object_new (NM_TYPE_REMOTE_SETTINGS,
+ NM_REMOTE_SETTINGS_BUS, bus,
+ NULL);
+ g_async_initable_init_async (G_ASYNC_INITABLE (self), G_PRIORITY_DEFAULT,
+ cancellable, remote_settings_inited, simple);
+}
+
+/**
+ * nm_remote_settings_new_finish:
+ * @result: a #GAsyncResult
+ * @error: location for a #GError, or %NULL
*
- * Returns: the new remote settings object on success, or %NULL on failure
+ * Gets the result of an nm_remote_settings_new_async() call.
+ *
+ * Returns: a new #NMRemoteSettings object, or %NULL on error
**/
NMRemoteSettings *
-nm_remote_settings_new (DBusGConnection *bus)
+nm_remote_settings_new_finish (GAsyncResult *result, GError **error)
{
- return (NMRemoteSettings *) g_object_new (NM_TYPE_REMOTE_SETTINGS,
- NM_REMOTE_SETTINGS_BUS, bus,
- NULL);
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, nm_remote_settings_new_async), NULL);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return NULL;
+ else
+ return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
}
+
static void
nm_remote_settings_init (NMRemoteSettings *self)
{
@@ -758,7 +801,6 @@ static void
constructed (GObject *object)
{
NMRemoteSettingsPrivate *priv;
- GError *error = NULL;
priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object);
@@ -781,19 +823,6 @@ constructed (GObject *object)
G_CALLBACK (name_owner_changed),
object, NULL);
- if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", &error,
- G_TYPE_STRING, NM_DBUS_SERVICE,
- G_TYPE_INVALID,
- G_TYPE_BOOLEAN, &priv->service_running,
- G_TYPE_INVALID)) {
- g_warning ("%s (NMRemoteSettings) error getting remote settings service status: (%d) %s\n",
- __func__,
- error ? error->code : -1,
- error && error->message ? error->message : "(unknown)");
- g_error_free (error);
- priv->service_running = FALSE;
- }
-
priv->proxy = dbus_g_proxy_new_for_name (priv->bus,
NM_DBUS_SERVICE,
NM_DBUS_PATH_SETTINGS,
@@ -831,15 +860,136 @@ constructed (GObject *object)
G_CALLBACK (properties_changed_cb),
object,
NULL);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+ NMRemoteSettings *settings = NM_REMOTE_SETTINGS (initable);
+ NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings);
+ GHashTable *props;
+
+ if (!dbus_g_proxy_call (priv->dbus_proxy, "NameHasOwner", error,
+ G_TYPE_STRING, NM_DBUS_SERVICE,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, &priv->service_running,
+ G_TYPE_INVALID)) {
+ priv->service_running = FALSE;
+ return FALSE;
+ }
/* Get properties */
+ if (!dbus_g_proxy_call (priv->props_proxy, "GetAll", error,
+ G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
+ G_TYPE_INVALID,
+ DBUS_TYPE_G_MAP_OF_VARIANT, &props,
+ G_TYPE_INVALID))
+ return FALSE;
+ properties_changed_cb (priv->props_proxy, props, settings);
+ g_hash_table_destroy (props);
+
+ /* FIXME: need a synchronous fetch_connections too */
+
+ return TRUE;
+}
+
+typedef struct {
+ NMRemoteSettings *settings;
+ GSimpleAsyncResult *result;
+} NMRemoteSettingsInitData;
+
+static void
+init_async_complete (NMRemoteSettingsInitData *init_data)
+{
+ g_simple_async_result_complete (init_data->result);
+ g_object_unref (init_data->result);
+ g_slice_free (NMRemoteSettingsInitData, init_data);
+}
+
+static void
+init_read_connections (NMRemoteSettings *settings, gpointer user_data)
+{
+ NMRemoteSettingsInitData *init_data = user_data;
+
+ g_signal_handlers_disconnect_by_func (settings, G_CALLBACK (init_read_connections), user_data);
+ init_async_complete (init_data);
+}
+
+static void
+init_async_got_properties (DBusGProxy *proxy, DBusGProxyCall *call,
+ gpointer user_data)
+{
+ NMRemoteSettingsInitData *init_data = user_data;
+ NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
+ GHashTable *props;
+ GError *error = NULL;
+
+ if (dbus_g_proxy_end_call (proxy, call, &error,
+ DBUS_TYPE_G_MAP_OF_VARIANT, &props,
+ G_TYPE_INVALID)) {
+ properties_changed_cb (priv->props_proxy, props, init_data->settings);
+ g_hash_table_destroy (props);
+ g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+ } else
+ g_simple_async_result_take_error (init_data->result, error);
+
+ if (priv->init_left) {
+ /* Still creating initial connections; wait for that to complete */
+ g_signal_connect (init_data->settings, "connections-read",
+ G_CALLBACK (init_read_connections), init_data);
+ return;
+ }
+
+ init_async_complete (init_data);
+}
+
+static void
+init_async_got_manager_running (DBusGProxy *proxy, DBusGProxyCall *call,
+ gpointer user_data)
+{
+ NMRemoteSettingsInitData *init_data = user_data;
+ NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (init_data->settings);
+ GError *error = NULL;
+
+ if (!dbus_g_proxy_end_call (proxy, call, &error,
+ G_TYPE_BOOLEAN, &priv->service_running,
+ G_TYPE_INVALID)) {
+ g_simple_async_result_take_error (init_data->result, error);
+ init_async_complete (init_data);
+ return;
+ }
+
+ if (!priv->service_running) {
+ g_simple_async_result_set_op_res_gboolean (init_data->result, TRUE);
+ init_async_complete (init_data);
+ return;
+ }
+
dbus_g_proxy_begin_call (priv->props_proxy, "GetAll",
- get_all_cb,
- object,
- NULL,
+ init_async_got_properties, init_data, NULL,
G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS,
- G_TYPE_INVALID);
+ G_TYPE_INVALID);
+}
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+ GCancellable *cancellable, GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ NMRemoteSettingsInitData *init_data;
+ NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (initable);
+
+ init_data = g_slice_new0 (NMRemoteSettingsInitData);
+ init_data->settings = NM_REMOTE_SETTINGS (initable);
+ init_data->result = g_simple_async_result_new (G_OBJECT (initable), callback,
+ user_data, init_async);
+
+ /* Check if NM is running */
+ dbus_g_proxy_begin_call (priv->dbus_proxy, "NameHasOwner",
+ init_async_got_manager_running,
+ init_data, NULL,
+ G_TYPE_STRING, NM_DBUS_SERVICE,
+ G_TYPE_INVALID);
}
static void
@@ -987,3 +1137,14 @@ nm_remote_settings_class_init (NMRemoteSettingsClass *class)
G_TYPE_NONE, 0);
}
+static void
+nm_remote_settings_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = init_sync;
+}
+
+static void
+nm_remote_settings_async_initable_iface_init (GAsyncInitableIface *iface)
+{
+ iface->init_async = init_async;
+}
diff --git a/libnm-glib/nm-remote-settings.h b/libnm-glib/nm-remote-settings.h
index e882e4f..6eb8ae5 100644
--- a/libnm-glib/nm-remote-settings.h
+++ b/libnm-glib/nm-remote-settings.h
@@ -24,7 +24,7 @@
#ifndef NM_REMOTE_SETTINGS_H
#define NM_REMOTE_SETTINGS_H
-#include <glib.h>
+#include <gio/gio.h>
#include <dbus/dbus-glib.h>
#include <nm-connection.h>
#include <nm-remote-connection.h>
@@ -110,6 +110,13 @@ GType nm_remote_settings_get_type (void);
NMRemoteSettings *nm_remote_settings_new (DBusGConnection *bus);
+void nm_remote_settings_new_async (DBusGConnection *bus,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+NMRemoteSettings *nm_remote_settings_new_finish (GAsyncResult *result,
+ GError **error);
+
GSList *nm_remote_settings_list_connections (NMRemoteSettings *settings);
NMRemoteConnection * nm_remote_settings_get_connection_by_path (NMRemoteSettings *settings,
--
1.7.7.5
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]