2007-10-07 Dan Williams <dcbw@redhat.com>

* src/nm-manager.c
	  src/nm-manager.h
		- Add a 'connections-added' signal to batch together updates of large
			numbers of connections, like when reading from a settings service
			the first time.  Otherwise, the policy would just activate the first
			suitable connection it saw rather than waiting for the full list
			to arrive.
		- (nm_manager_class_init): register new signal
		- (get_type_for_proxy, connection_get_settings_cb,
		   get_connection_for_proxy): centralize places where a proxy's setting
			service is determined
		- (free_get_settings_info): if the call being freed is the last call
			in a pending call group, fire off the connections-added signal
		- (internal_new_connection_cb): add call to a pending call group if
			requested
		- (list_connections_cb): always create a call group here, because this
			call results in a batch of new connections
		- (initial_get_connections): start getting system connections first
		- (nm_manager_connections_destroy, emit_removed): actually emit the
			removed signal when destroying connections

	* src/NetworkManagerPolicy.c
		- (nm_policy_new, connections_added): handle connections-added signal
			from the manager



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2951 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams 2007-10-07 23:33:28 +00:00
parent b6c662e442
commit 9d318e9fae
4 changed files with 177 additions and 38 deletions

View file

@ -1,3 +1,30 @@
2007-10-07 Dan Williams <dcbw@redhat.com>
* src/nm-manager.c
src/nm-manager.h
- Add a 'connections-added' signal to batch together updates of large
numbers of connections, like when reading from a settings service
the first time. Otherwise, the policy would just activate the first
suitable connection it saw rather than waiting for the full list
to arrive.
- (nm_manager_class_init): register new signal
- (get_type_for_proxy, connection_get_settings_cb,
get_connection_for_proxy): centralize places where a proxy's setting
service is determined
- (free_get_settings_info): if the call being freed is the last call
in a pending call group, fire off the connections-added signal
- (internal_new_connection_cb): add call to a pending call group if
requested
- (list_connections_cb): always create a call group here, because this
call results in a batch of new connections
- (initial_get_connections): start getting system connections first
- (nm_manager_connections_destroy, emit_removed): actually emit the
removed signal when destroying connections
* src/NetworkManagerPolicy.c
- (nm_policy_new, connections_added): handle connections-added signal
from the manager
2007-10-06 Dan Williams <dcbw@redhat.com>
* src/nm-device-802-11-wireless.c

View file

@ -475,6 +475,16 @@ state_changed (NMManager *manager, NMState state, gpointer user_data)
}
}
static void
connections_added (NMManager *manager,
NMConnectionType connection_type,
gpointer user_data)
{
NMPolicy *policy = (NMPolicy *) user_data;
schedule_change_check (policy);
}
static void
connection_added (NMManager *manager,
NMConnection *connection,
@ -544,6 +554,13 @@ nm_policy_new (NMManager *manager)
g_signal_connect (manager, "state-change",
G_CALLBACK (state_changed), policy);
/* Large batch of connections added, manager doesn't want us to
* process each one individually.
*/
g_signal_connect (manager, "connections-added",
G_CALLBACK (connections_added), policy);
/* Single connection added */
g_signal_connect (manager, "connection-added",
G_CALLBACK (connection_added), policy);

View file

@ -75,6 +75,7 @@ enum {
DEVICE_ADDED,
DEVICE_REMOVED,
STATE_CHANGE,
CONNECTIONS_ADDED,
CONNECTION_ADDED,
CONNECTION_UPDATED,
CONNECTION_REMOVED,
@ -291,6 +292,16 @@ nm_manager_class_init (NMManagerClass *manager_class)
G_TYPE_NONE, 1,
G_TYPE_UINT);
signals[CONNECTIONS_ADDED] =
g_signal_new ("connections-added",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMManagerClass, connections_added),
NULL, NULL,
g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1,
G_TYPE_UINT);
signals[CONNECTION_ADDED] =
g_signal_new ("connection-added",
G_OBJECT_CLASS_TYPE (object_class),
@ -328,9 +339,25 @@ nm_manager_class_init (NMManagerClass *manager_class)
#define DBUS_TYPE_G_STRING_VARIANT_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE))
#define DBUS_TYPE_G_DICT_OF_DICTS (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, DBUS_TYPE_G_STRING_VARIANT_HASHTABLE))
static NMConnectionType
get_type_for_proxy (DBusGProxy *proxy)
{
const char *bus_name = dbus_g_proxy_get_bus_name (proxy);
if (strcmp (bus_name, NM_DBUS_SERVICE_USER_SETTINGS) == 0)
return NM_CONNECTION_TYPE_USER;
else if (strcmp (bus_name, NM_DBUS_SERVICE_SYSTEM_SETTINGS) == 0)
return NM_CONNECTION_TYPE_SYSTEM;
return NM_CONNECTION_TYPE_UNKNOWN;
}
typedef struct GetSettingsInfo {
NMManager *manager;
NMConnection *connection;
DBusGProxy *proxy;
DBusGProxyCall *call;
GSList **calls;
} GetSettingsInfo;
static void
@ -338,6 +365,20 @@ free_get_settings_info (gpointer data)
{
GetSettingsInfo *info = (GetSettingsInfo *) data;
/* If this was the last pending call for a batch of GetSettings calls,
* send out the connections-added signal.
*/
if (info->calls) {
*(info->calls) = g_slist_remove (*(info->calls), info->call);
if (g_slist_length (*(info->calls)) == 0) {
g_slist_free (*(info->calls));
g_signal_emit (info->manager,
signals[CONNECTIONS_ADDED],
0,
get_type_for_proxy (info->proxy));
}
}
if (info->manager) {
g_object_unref (info->manager);
info->manager = NULL;
@ -359,7 +400,7 @@ connection_get_settings_cb (DBusGProxy *proxy,
GError *err = NULL;
GHashTable *settings = NULL;
NMConnection *connection;
NMConnectionType connection_type;
NMConnectionType type;
NMManager *manager;
g_return_if_fail (info != NULL);
@ -376,7 +417,6 @@ connection_get_settings_cb (DBusGProxy *proxy,
connection = info->connection;
if (connection == NULL) {
const char *path = dbus_g_proxy_get_path (proxy);
const char *bus_name = dbus_g_proxy_get_bus_name (proxy);
NMManagerPrivate *priv;
connection = nm_connection_new_from_hash (settings);
@ -389,26 +429,33 @@ connection_get_settings_cb (DBusGProxy *proxy,
(GDestroyNotify) g_object_unref);
priv = NM_MANAGER_GET_PRIVATE (manager);
if (strcmp (bus_name, NM_DBUS_SERVICE_USER_SETTINGS) == 0) {
connection_type = NM_CONNECTION_TYPE_USER;
g_hash_table_insert (priv->user_connections,
g_strdup (path),
connection);
} else if (strcmp (bus_name, NM_DBUS_SERVICE_SYSTEM_SETTINGS) == 0) {
connection_type = NM_CONNECTION_TYPE_SYSTEM;
g_hash_table_insert (priv->system_connections,
g_strdup (path),
connection);
} else {
nm_warning ("Connection wasn't a user connection or a system connection.");
g_assert_not_reached ();
type = get_type_for_proxy (proxy);
switch (type) {
case NM_CONNECTION_TYPE_USER:
g_hash_table_insert (priv->user_connections,
g_strdup (path),
connection);
break;
case NM_CONNECTION_TYPE_SYSTEM:
g_hash_table_insert (priv->system_connections,
g_strdup (path),
connection);
break;
default:
nm_warning ("Connection wasn't a user connection or a system connection.");
g_assert_not_reached ();
break;
}
g_object_set_data (G_OBJECT (connection),
NM_MANAGER_CONNECTION_TYPE_TAG,
GUINT_TO_POINTER (connection_type));
GUINT_TO_POINTER (type));
g_signal_emit (manager, signals[CONNECTION_ADDED], 0, connection, connection_type);
/* If the connection-added signal is supposed to be batched, don't
* emit the single connection-added here.
*/
if (!info->calls)
g_signal_emit (manager, signals[CONNECTION_ADDED], 0, connection, type);
} else {
// FIXME: merge settings? or just replace?
nm_warning ("%s (#%d): implement merge settings", __func__, __LINE__);
@ -427,20 +474,27 @@ get_connection_for_proxy (NMManager *manager,
const char **out_path)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
NMConnection *connection = NULL;
const char *path = dbus_g_proxy_get_path (proxy);
const char *bus_name = dbus_g_proxy_get_bus_name (proxy);
if (out_path)
*out_path = path;
if (strcmp (bus_name, NM_DBUS_SERVICE_USER_SETTINGS) == 0) {
*out_hash = priv->user_connections;
return g_hash_table_lookup (priv->user_connections, path);
} else if (strcmp (bus_name, NM_DBUS_SERVICE_SYSTEM_SETTINGS) == 0) {
*out_hash = priv->system_connections;
return g_hash_table_lookup (priv->system_connections, path);
switch (get_type_for_proxy (proxy)) {
case NM_CONNECTION_TYPE_USER:
*out_hash = priv->user_connections;
connection = g_hash_table_lookup (priv->user_connections, path);
break;
case NM_CONNECTION_TYPE_SYSTEM:
*out_hash = priv->system_connections;
connection = g_hash_table_lookup (priv->system_connections, path);
break;
default:
nm_warning ("Connection wasn't a user connection or a system connection.");
g_assert_not_reached ();
break;
}
return NULL;
return connection;
}
static void
@ -449,7 +503,7 @@ remove_connection (NMManager *manager,
GHashTable *hash,
const char *path)
{
NMConnectionType type = NM_CONNECTION_TYPE_UNKNOWN;
NMConnectionType type;
/* Destroys the connection, then associated DBusGProxy due to the
* weak reference notify function placed on the connection when it
@ -510,19 +564,21 @@ connection_updated_cb (DBusGProxy *proxy, GHashTable *settings, gpointer user_da
}
static void
new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
internal_new_connection_cb (DBusGProxy *proxy,
const char *path,
NMManager *manager,
GSList **calls)
{
NMManager * manager = NM_MANAGER (user_data);
struct GetSettingsInfo *info;
DBusGProxy *con_proxy;
NMDBusManager * dbus_mgr;
DBusGConnection * g_connection;
DBusGProxyCall *call;
struct GetSettingsInfo *info;
dbus_mgr = nm_dbus_manager_get ();
g_connection = nm_dbus_manager_get_connection (dbus_mgr);
con_proxy = dbus_g_proxy_new_for_name (g_connection,
NM_DBUS_SERVICE_USER_SETTINGS,
dbus_g_proxy_get_bus_name (proxy),
path,
NM_DBUS_IFACE_SETTINGS_CONNECTION);
g_object_unref (dbus_mgr);
@ -547,11 +603,16 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
info = g_slice_new0 (GetSettingsInfo);
info->manager = g_object_ref (manager);
info->calls = calls;
call = dbus_g_proxy_begin_call (con_proxy, "GetSettings",
connection_get_settings_cb,
info,
free_get_settings_info,
G_TYPE_INVALID);
info->call = call;
info->proxy = con_proxy;
if (info->calls)
*(info->calls) = g_slist_prepend (*(info->calls), call);
}
#define DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH))
@ -564,6 +625,7 @@ list_connections_cb (DBusGProxy *proxy,
NMManager *manager = NM_MANAGER (user_data);
GError *err = NULL;
GPtrArray *ops;
GSList **calls = NULL;
int i;
if (!dbus_g_proxy_end_call (proxy, call_id, &err,
@ -574,8 +636,17 @@ list_connections_cb (DBusGProxy *proxy,
goto out;
}
for (i = 0; i < ops->len; i++)
new_connection_cb (proxy, g_ptr_array_index (ops, i), manager);
/* Keep track of all calls made here; don't want to emit connection-added for
* each one, but emit connections-added when they are all done.
*/
calls = g_slice_new0 (GSList *);
for (i = 0; i < ops->len; i++) {
internal_new_connection_cb (proxy,
g_ptr_array_index (ops, i),
manager,
calls);
}
g_ptr_array_free (ops, TRUE);
@ -583,6 +654,12 @@ out:
return;
}
static void
new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data)
{
internal_new_connection_cb (proxy, path, NM_MANAGER (user_data), NULL);
}
static void
query_connections (NMManager *manager,
NMConnectionType type)
@ -676,14 +753,14 @@ initial_get_connections (gpointer user_data)
{
NMManager * manager = NM_MANAGER (user_data);
if (nm_dbus_manager_name_has_owner (nm_dbus_manager_get (),
NM_DBUS_SERVICE_USER_SETTINGS))
query_connections (manager, NM_CONNECTION_TYPE_USER);
if (nm_dbus_manager_name_has_owner (nm_dbus_manager_get (),
NM_DBUS_SERVICE_SYSTEM_SETTINGS))
query_connections (manager, NM_CONNECTION_TYPE_SYSTEM);
if (nm_dbus_manager_name_has_owner (nm_dbus_manager_get (),
NM_DBUS_SERVICE_USER_SETTINGS))
query_connections (manager, NM_CONNECTION_TYPE_USER);
return FALSE;
}
@ -713,6 +790,17 @@ nm_manager_new (void)
return NM_MANAGER (object);
}
static void
emit_removed (gpointer key, gpointer value, gpointer user_data)
{
NMManager *manager = NM_MANAGER (user_data);
NMConnection *connection = NM_CONNECTION (value);
NMConnectionType type;
type = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), NM_MANAGER_CONNECTION_TYPE_TAG));
g_signal_emit (manager, signals[CONNECTION_REMOVED], 0, connection, type);
}
static void
nm_manager_connections_destroy (NMManager *manager,
NMConnectionType type)
@ -720,16 +808,20 @@ nm_manager_connections_destroy (NMManager *manager,
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
if (type == NM_CONNECTION_TYPE_USER) {
if (priv->user_connections)
if (priv->user_connections) {
g_hash_table_foreach (priv->user_connections, emit_removed, manager);
g_hash_table_remove_all (priv->user_connections);
}
if (priv->user_proxy) {
g_object_unref (priv->user_proxy);
priv->user_proxy = NULL;
}
} else if (type == NM_CONNECTION_TYPE_SYSTEM) {
if (priv->system_connections)
if (priv->system_connections) {
g_hash_table_foreach (priv->system_connections, emit_removed, manager);
g_hash_table_remove_all (priv->system_connections);
}
if (priv->system_proxy) {
g_object_unref (priv->system_proxy);

View file

@ -37,6 +37,9 @@ typedef struct {
void (*device_added) (NMManager *manager, NMDevice *device);
void (*device_removed) (NMManager *manager, NMDevice *device);
void (*state_change) (NMManager *manager, guint state);
void (*connections_added) (NMManager *manager, NMConnectionType type);
void (*connection_added) (NMManager *manager,
NMConnection *connection,
NMConnectionType connection_type);