[PATCH] service: Keep ordering and send all services in ServicesAdded

patrik.flykt at linux.intel.com patrik.flykt at linux.intel.com
Mon Feb 27 06:56:35 PST 2012


From: Patrik Flykt <patrik.flykt at linux.intel.com>

Keep services ordering and send also already known services
in ServicesAdded signal.
---
 src/service.c |  144 ++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 81 insertions(+), 63 deletions(-)

diff --git a/src/service.c b/src/service.c
index a21ee3f..271aace 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1996,27 +1996,43 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
 						append_provider, service);
 }
 
-static void append_struct(gpointer value, gpointer user_data)
+static void append_struct_service(DBusMessageIter *iter,
+		connman_dbus_append_cb_t function,
+		struct connman_service *service)
 {
-	struct connman_service *service = value;
-	DBusMessageIter *iter = user_data;
 	DBusMessageIter entry, dict;
 
-	if (service->path == NULL)
-		return;
-
 	dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry);
 
 	dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
 							&service->path);
 
 	connman_dbus_dict_open(&entry, &dict);
-	append_properties(&dict, TRUE, service);
+	if (function != NULL)
+		function(&dict, service);
 	connman_dbus_dict_close(&entry, &dict);
 
 	dbus_message_iter_close_container(iter, &entry);
 }
 
+static void append_dict_properties(DBusMessageIter *dict, void *user_data)
+{
+	struct connman_service *service = user_data;
+
+	append_properties(dict, TRUE, service);
+}
+
+static void append_struct(gpointer value, gpointer user_data)
+{
+	struct connman_service *service = value;
+	DBusMessageIter *iter = user_data;
+
+	if (service->path == NULL)
+		return;
+
+	append_struct_service(iter, append_dict_properties, service);
+}
+
 void __connman_service_list_struct(DBusMessageIter *iter)
 {
 	g_sequence_foreach(service_list, append_struct, iter);
@@ -3263,18 +3279,23 @@ static DBusMessage *reset_counters(DBusConnection *conn,
 
 static struct _services_notify {
 	int id;
-	GSList *added;
-	GSList *removed;
+	GHashTable *add;
+	GHashTable *remove;
 } *services_notify;
 
+static void append_removed(gpointer key, gpointer value, gpointer user_data)
+{
+	char *objpath = key;
+	DBusMessageIter *iter = user_data;
+
+	DBG("removed %s", objpath);
+	dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &objpath);
+}
+
 static void service_send_removed(void)
 {
 	DBusMessage *signal;
 	DBusMessageIter iter, array;
-	GSList *list, *next;
-
-	if (services_notify->removed == NULL)
-		return;
 
 	signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
 			CONNMAN_MANAGER_INTERFACE, "ServicesRemoved");
@@ -3285,57 +3306,57 @@ static void service_send_removed(void)
 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
 			DBUS_TYPE_OBJECT_PATH_AS_STRING, &array);
 
-	list = services_notify->removed;
-	services_notify->removed = NULL;
+	g_hash_table_foreach(services_notify->remove, append_removed, &array);
 
-	while (list != NULL) {
-		char *path = list->data;
-		DBG("removing %s", path);
-		next = list->next;
-		dbus_message_iter_append_basic(&array,
-				DBUS_TYPE_OBJECT_PATH, &list->data);
-		g_free(list->data);
-		g_slist_free_1(list);
-		list = next;
-	}
 	dbus_message_iter_close_container(&iter, &array);
 
 	dbus_connection_send(connection, signal, NULL);
 	dbus_message_unref(signal);
 }
 
-static void append_service_structs(DBusMessageIter *iter, void *user_data)
+static void service_send_added_foreach(gpointer data, gpointer user_data)
 {
-	GSList *list = user_data;
-	GSList *next;
+	struct connman_service *service = data;
+	DBusMessageIter *iter = user_data;
+	gpointer value;
+
+	if (service == NULL || service->path == NULL) {
+		DBG("service %p or path is NULL", service);
+		return;
+	}
 
-	while (list != NULL) {
-		struct connman_service *srv = list->data;
-		DBG("adding %s", srv->path);
-		next = list->next;
-		append_struct(list->data, iter);
-		g_slist_free_1(list);
-		list = next;
+	value = g_hash_table_lookup(services_notify->remove, service->path);
+	if (GPOINTER_TO_INT(value) == TRUE) {
+		g_hash_table_remove(services_notify->remove, service->path);
+		return;
 	}
+
+	DBG("added %s", service->path);
+
+	if (g_hash_table_lookup(services_notify->add, service->path) != NULL) {
+		append_struct(service, iter);
+		g_hash_table_remove(services_notify->add, service->path);
+	} else {
+		append_struct_service(iter, NULL, service);
+	}
+}
+
+static void service_send_added_ordered(DBusMessageIter *iter, void *user_data)
+{
+	g_sequence_foreach(service_list, service_send_added_foreach, iter);
 }
 
 static void service_send_added(void)
 {
 	DBusMessage *signal;
-	GSList *list;
-
-	if (services_notify->added == NULL)
-		return;
 
 	signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
 			CONNMAN_MANAGER_INTERFACE, "ServicesAdded");
 	if (signal == NULL)
 		return;
 
-	list = services_notify->added;
-	services_notify->added = NULL;
 	__connman_dbus_append_objpath_dict_array(signal,
-			append_service_structs, list);
+			service_send_added_ordered, NULL);
 
 	dbus_connection_send(connection, signal, NULL);
 	dbus_message_unref(signal);
@@ -3343,8 +3364,13 @@ static void service_send_added(void)
 
 static gboolean service_send_signals(gpointer data)
 {
-	service_send_removed();
-	service_send_added();
+	if (g_hash_table_size(services_notify->remove) > 0)
+		service_send_removed();
+
+	if (g_hash_table_size(services_notify->add) > 0)
+		service_send_added();
+	else
+		g_hash_table_remove_all(services_notify->remove);
 
 	services_notify->id = 0;
 	return FALSE;
@@ -3362,37 +3388,24 @@ static void service_schedule_added(struct connman_service *service)
 {
 	DBG("service %p", service);
 
-	services_notify->added = g_slist_prepend(services_notify->added,
-			service);
+	g_hash_table_remove(services_notify->remove, service->path);
+	g_hash_table_insert(services_notify->add, service->path, service);
 
 	service_schedule_signals();
 }
 
 static void service_schedule_removed(struct connman_service *service)
 {
-	GSList *list;
-
-	DBG("service %p", service);
+	DBG("service %p %s", service, service->path);
 
 	if (service == NULL || service->path == NULL) {
 		DBG("service %p or path is NULL", service);
 		return;
 	}
 
-	for (list = services_notify->added; list != NULL; list = list->next) {
-		struct connman_service *srv = list->data;
-		if (service == srv) {
-			DBG("delete service %p from added list", srv);
-			break;
-		}
-	}
-
-	if (list != NULL)
-		services_notify->added =
-			g_slist_delete_link(services_notify->added, list);
-
-	services_notify->removed = g_slist_prepend(services_notify->removed,
-			g_strdup(service->path));
+	g_hash_table_remove(services_notify->add, service->path);
+	g_hash_table_insert(services_notify->remove, g_strdup(service->path),
+			GINT_TO_POINTER(TRUE));
 
 	service_schedule_signals();
 }
@@ -5487,6 +5500,9 @@ int __connman_service_init(void)
 	service_list = g_sequence_new(service_free);
 
 	services_notify = g_new0(struct _services_notify, 1);
+	services_notify->remove = g_hash_table_new_full(g_str_hash,
+			g_str_equal, g_free, NULL);
+	services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
 
 	return 0;
 }
@@ -5510,6 +5526,8 @@ void __connman_service_cleanup(void)
 	if (services_notify->id != 0) {
 		g_source_remove(services_notify->id);
 		service_send_signals(NULL);
+		g_hash_table_destroy(services_notify->remove);
+		g_hash_table_destroy(services_notify->add);
 	}
 	g_free(services_notify);
 
-- 
1.7.9




More information about the connman mailing list