From c6dc4196705b7b93e11b6687b10cc49a7f038c34 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 7 Apr 2009 16:54:19 -0700 Subject: [PATCH] Add service initialization and lifetime tracking support --- include/service.h | 3 ++ src/connman.h | 3 ++ src/element.c | 2 + src/service.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+) diff --git a/include/service.h b/include/service.h index 9e97cf6..e83911c 100644 --- a/include/service.h +++ b/include/service.h @@ -65,6 +65,9 @@ enum connman_service_state { struct connman_service; +extern struct connman_service *connman_service_get(const char *identifier); +extern void connman_service_put(struct connman_service *service); + #ifdef __cplusplus } #endif diff --git a/src/connman.h b/src/connman.h index 44cba11..a97dfad 100644 --- a/src/connman.h +++ b/src/connman.h @@ -209,6 +209,9 @@ int __connman_profile_remove_network(struct connman_network *network); #include +int __connman_service_init(void); +void __connman_service_cleanup(void); + #include int __connman_notifier_init(void); diff --git a/src/element.c b/src/element.c index b68e954..7b24a98 100644 --- a/src/element.c +++ b/src/element.c @@ -1284,6 +1284,7 @@ int __connman_element_init(DBusConnection *conn, const char *device, element_root = g_node_new(element); __connman_notifier_init(); + __connman_service_init(); __connman_network_init(); __connman_device_init(); @@ -1368,6 +1369,7 @@ void __connman_element_cleanup(void) __connman_device_cleanup(); __connman_network_cleanup(); + __connman_service_cleanup(); __connman_notifier_cleanup(); g_node_traverse(element_root, G_POST_ORDER, G_TRAVERSE_ALL, -1, diff --git a/src/service.c b/src/service.c index f272fe3..9c95fc6 100644 --- a/src/service.c +++ b/src/service.c @@ -25,7 +25,14 @@ #include "connman.h" +static DBusConnection *connection = NULL; + +static GSequence *service_list = NULL; +static GHashTable *service_hash = NULL; + struct connman_service { + gint refcount; + char *identifier; char *path; enum connman_service_type type; enum connman_service_mode mode; @@ -35,3 +42,104 @@ struct connman_service { connman_bool_t favorite; char *name; }; + +static void service_free(gpointer data) +{ + struct connman_service *service = data; + + DBG("service %p", service); + + g_hash_table_remove(service_hash, service->identifier); + + g_free(service->name); + g_free(service->path); + g_free(service->identifier); + g_free(service); +} + +static gint service_compare(gconstpointer a, gconstpointer b, + gpointer user_data) +{ + struct connman_service *service_a = (void *) a; + struct connman_service *service_b = (void *) b; + + if (service_a->favorite == TRUE && service_b->favorite == FALSE) + return -1; + + if (service_a->favorite == FALSE && service_b->favorite == TRUE) + return 1; + + return (gint) service_b->strength - (gint) service_a->strength; +} + +struct connman_service *connman_service_get(const char *identifier) +{ + struct connman_service *service; + GSequenceIter *iter; + + iter = g_hash_table_lookup(service_hash, identifier); + if (iter != NULL) { + service = g_sequence_get(iter); + if (service != NULL) + g_atomic_int_inc(&service->refcount); + return service; + } + + service = g_try_new0(struct connman_service, 1); + if (service == NULL) + return NULL; + + DBG("service %p", service); + + service->refcount = 1; + service->identifier = g_strdup(identifier); + + iter = g_sequence_insert_sorted(service_list, service, + service_compare, NULL); + + g_hash_table_insert(service_hash, service->identifier, iter); + + return service; +} + +void connman_service_put(struct connman_service *service) +{ + DBG("service %p", service); + + if (g_atomic_int_dec_and_test(&service->refcount) == TRUE) { + GSequenceIter *iter; + + iter = g_hash_table_lookup(service_hash, service->identifier); + if (iter != NULL) + g_sequence_remove(iter); + else + service_free(service); + } +} + +int __connman_service_init(void) +{ + DBG(""); + + connection = connman_dbus_get_connection(); + + service_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, NULL); + + service_list = g_sequence_new(service_free); + + return 0; +} + +void __connman_service_cleanup(void) +{ + DBG(""); + + g_sequence_free(service_list); + service_list = NULL; + + g_hash_table_destroy(service_hash); + service_hash = NULL; + + dbus_connection_unref(connection); +} -- 1.7.9.5