From: Patrik Flykt <[email protected]>
When services are added or removed, collect them into separate
lists in order to send as many as possible in one go and with
then removed ones sent first. Add a wait of 100ms to collect
more services in one batch. When removing a service check
whether it was also on the added list; if so, remove it from
that list.
---
src/manager.c | 2 +
src/service.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 146 insertions(+), 0 deletions(-)
diff --git a/src/manager.c b/src/manager.c
index cf2c624..7cf1eec 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -439,6 +439,8 @@ static GDBusSignalTable manager_signals[] = {
{ "PropertyChanged", "sv" },
{ "TechnologyAdded", "a{sv}" },
{ "TechnologyRemoved", "o" },
+ { "ServicesAdded", "a(oa{sv})" },
+ { "ServicesRemoved", "a{o}" },
{ },
};
diff --git a/src/service.c b/src/service.c
index b0acd5f..d9bb8bc 100644
--- a/src/service.c
+++ b/src/service.c
@@ -3318,6 +3318,143 @@ static DBusMessage *reset_counters(DBusConnection *conn,
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
+static struct _services_notify {
+ int id;
+ GSList *added;
+ GSList *removed;
+} *services_notify;
+
+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");
+ if (signal == NULL)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_OBJECT_PATH_AS_STRING, &array);
+
+ list = services_notify->removed;
+ services_notify->removed = NULL;
+
+ 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 service_send_added(void)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter, array;
+ GSList *list, *next;
+
+ if (services_notify->added == NULL)
+ return;
+
+ signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
+ CONNMAN_MANAGER_INTERFACE, "ServicesAdded");
+ if (signal == NULL)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_OBJECT_PATH_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING, &array);
+
+ list = services_notify->added;
+ services_notify->added = NULL;
+
+ while (list != NULL) {
+ struct connman_service *srv = list->data;
+ DBG("adding %s", srv->path);
+ next = list->next;
+ append_struct(list->data, &array);
+ 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 gboolean service_send_signals(gpointer data)
+{
+ service_send_removed();
+ service_send_added();
+
+ services_notify->id = 0;
+ return FALSE;
+}
+
+static void service_schedule_signals(void)
+{
+ if (services_notify->id != 0)
+ g_source_remove(services_notify->id);
+
+ services_notify->id = g_timeout_add(100, service_send_signals, NULL);
+}
+
+static void service_schedule_added(struct connman_service *service)
+{
+ DBG("service %p", service);
+
+ services_notify->added = g_slist_prepend(services_notify->added,
+ service);
+
+ service_schedule_signals();
+}
+
+static void service_schedule_removed(struct connman_service *service)
+{
+ GSList *list;
+
+ DBG("service %p", service);
+
+ 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));
+
+ service_schedule_signals();
+}
+
static GDBusMethodTable service_methods[] = {
{ "GetProperties", "", "a{sv}", get_properties },
{ "SetProperty", "sv", "", set_property },
@@ -3349,6 +3486,7 @@ static void service_free(gpointer user_data)
g_hash_table_remove(service_hash, service->identifier);
__connman_notifier_service_remove(service);
+ service_schedule_removed(service);
stats_stop(service);
@@ -5247,6 +5385,7 @@ struct connman_service *
__connman_service_create_from_network(struct connman_ne
}
__connman_notifier_service_add(service, service->name);
+ service_schedule_added(service);
return service;
}
@@ -5388,6 +5527,7 @@ __connman_service_create_from_provider(struct
connman_provider *provider)
service_register(service);
__connman_notifier_service_add(service, service->name);
+ service_schedule_added(service);
return service;
}
@@ -5403,6 +5543,8 @@ int __connman_service_init(void)
service_list = g_sequence_new(service_free);
+ services_notify = g_new0(struct _services_notify, 1);
+
return 0;
}
@@ -5422,5 +5564,7 @@ void __connman_service_cleanup(void)
g_slist_free(counter_list);
counter_list = NULL;
+ g_free(services_notify);
+
dbus_connection_unref(connection);
}
--
1.7.2.5
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman