From 7d36465e46ff59fb216b943df2e8c63c2e366bd1 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 20 Sep 2010 16:45:24 +0200 Subject: [PATCH] Handle several counters simultaniously The current implementation does not handle multiple counters at the same time correctly. Only the first counter gets the updates, all others just an empty dictionary. For each Counter object the counters have to be maintained separately. --- src/connman.h | 31 ++---- src/counter.c | 98 ++++------------- src/ipconfig.c | 2 +- src/service.c | 326 ++++++++++++++++++++++++++++++++++++++------------------- 4 files changed, 250 insertions(+), 207 deletions(-) diff --git a/src/connman.h b/src/connman.h index f26514a..f4ba942 100644 --- a/src/connman.h +++ b/src/connman.h @@ -66,25 +66,16 @@ void __connman_agent_cleanup(void); int __connman_agent_register(const char *sender, const char *path); int __connman_agent_unregister(const char *sender, const char *path); -struct connman_service; -struct connman_ipconfig; - +void __connman_counter_send_usage(const char *path, + DBusMessage *message); int __connman_counter_register(const char *owner, const char *path, unsigned int interval); int __connman_counter_unregister(const char *owner, const char *path); -void __connman_counter_notify(struct connman_ipconfig *config, - unsigned int rx_packets, unsigned int tx_packets, - unsigned int rx_bytes, unsigned int tx_bytes, - unsigned int rx_error, unsigned int tx_error, - unsigned int rx_dropped, unsigned int tx_dropped); - -int __connman_counter_add_service(struct connman_service *service); -void __connman_counter_remove_service(struct connman_service *service); - int __connman_counter_init(void); void __connman_counter_cleanup(void); +struct connman_service *service; typedef void (* passphrase_cb_t) (struct connman_service *service, const char *passphrase, void *user_data); @@ -502,14 +493,14 @@ const char *__connman_service_get_nameserver(struct connman_service *service); void __connman_service_set_proxy_autoconfig(struct connman_service *service, const char *url); -void __connman_service_stats_append(struct connman_service *service, - DBusMessage *msg, - connman_bool_t append_all); -connman_bool_t __connman_service_stats_update(struct connman_service *service, - unsigned int rx_packets, unsigned int tx_packets, - unsigned int rx_bytes, unsigned int tx_bytes, - unsigned int rx_error, unsigned int tx_error, - unsigned int rx_dropped, unsigned int tx_dropped); +void __connman_service_notify(struct connman_ipconfig *ipconfig, + unsigned int rx_packets, unsigned int tx_packets, + unsigned int rx_bytes, unsigned int tx_bytes, + unsigned int rx_error, unsigned int tx_error, + unsigned int rx_dropped, unsigned int tx_dropped); + +int __connman_service_counter_register(const char *counter); +void __connman_service_counter_unregister(const char *counter); #include diff --git a/src/counter.c b/src/counter.c index 19171e5..6a0a994 100644 --- a/src/counter.c +++ b/src/counter.c @@ -29,7 +29,6 @@ static DBusConnection *connection; -static GHashTable *stats_table; static GHashTable *counter_table; static GHashTable *owner_mapping; @@ -38,7 +37,6 @@ struct connman_counter { char *path; unsigned int interval; guint watch; - connman_bool_t first_update; }; static void remove_counter(gpointer user_data) @@ -52,6 +50,8 @@ static void remove_counter(gpointer user_data) __connman_rtnl_update_interval_remove(counter->interval); + __connman_service_counter_unregister(counter->path); + g_free(counter->owner); g_free(counter->path); g_free(counter); @@ -71,6 +71,7 @@ int __connman_counter_register(const char *owner, const char *path, unsigned int interval) { struct connman_counter *counter; + int err; DBG("owner %s path %s interval %u", owner, path, interval); @@ -84,7 +85,14 @@ int __connman_counter_register(const char *owner, const char *path, counter->owner = g_strdup(owner); counter->path = g_strdup(path); - counter->first_update = TRUE; + + err = __connman_service_counter_register(counter->path); + if (err < 0) { + g_free(counter->owner); + g_free(counter->path); + g_free(counter); + return err; + } g_hash_table_replace(counter_table, counter->path, counter); g_hash_table_replace(owner_mapping, counter->owner, counter); @@ -117,61 +125,24 @@ int __connman_counter_unregister(const char *owner, const char *path) return 0; } -static void send_usage(struct connman_counter *counter, - struct connman_service *service) +void __connman_counter_send_usage(const char *path, + DBusMessage *message) { - DBusMessage *message; - const char *service_path; + struct connman_counter *counter; - message = dbus_message_new_method_call(counter->owner, counter->path, - CONNMAN_COUNTER_INTERFACE, "Usage"); - if (message == NULL) + counter = g_hash_table_lookup(counter_table, path); + if (counter == NULL) return; + dbus_message_set_destination(message, counter->owner); + dbus_message_set_path(message, counter->path); + dbus_message_set_interface(message, CONNMAN_COUNTER_INTERFACE); + dbus_message_set_member(message, "Usage"); dbus_message_set_no_reply(message, TRUE); - service_path = __connman_service_get_path(service); - dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, - &service_path, DBUS_TYPE_INVALID); - - __connman_service_stats_append(service, message, counter->first_update); - - counter->first_update = FALSE; - g_dbus_send_message(connection, message); } -void __connman_counter_notify(struct connman_ipconfig *config, - unsigned int rx_packets, unsigned int tx_packets, - unsigned int rx_bytes, unsigned int tx_bytes, - unsigned int rx_errors, unsigned int tx_errors, - unsigned int rx_dropped, unsigned int tx_dropped) -{ - struct connman_service *service; - GHashTableIter iter; - gpointer key, value; - - service = g_hash_table_lookup(stats_table, config); - if (service == NULL) - return; - - if (__connman_service_stats_update(service, - rx_packets, tx_packets, - rx_bytes, tx_bytes, - rx_errors, tx_errors, - rx_dropped, tx_dropped) == FALSE) { - /* first update, counters are now initialized */ - return; - } - - g_hash_table_iter_init(&iter, counter_table); - while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { - struct connman_counter *counter = value; - - send_usage(counter, service); - } -} - static void release_counter(gpointer key, gpointer value, gpointer user_data) { struct connman_counter *counter = value; @@ -189,30 +160,6 @@ static void release_counter(gpointer key, gpointer value, gpointer user_data) g_dbus_send_message(connection, message); } -int __connman_counter_add_service(struct connman_service *service) -{ - struct connman_ipconfig *config; - - config = __connman_service_get_ipconfig(service); - g_hash_table_replace(stats_table, config, service); - - /* - * Trigger a first update to intialize the offset counters - * in the service. - */ - __connman_rtnl_request_update(); - - return 0; -} - -void __connman_counter_remove_service(struct connman_service *service) -{ - struct connman_ipconfig *config; - - config = __connman_service_get_ipconfig(service); - g_hash_table_remove(stats_table, config); -} - int __connman_counter_init(void) { DBG(""); @@ -221,9 +168,6 @@ int __connman_counter_init(void) if (connection == NULL) return -1; - stats_table = g_hash_table_new_full(g_direct_hash, g_str_equal, - NULL, NULL); - counter_table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, remove_counter); owner_mapping = g_hash_table_new_full(g_str_hash, g_str_equal, @@ -244,7 +188,5 @@ void __connman_counter_cleanup(void) g_hash_table_destroy(owner_mapping); g_hash_table_destroy(counter_table); - g_hash_table_destroy(stats_table); - dbus_connection_unref(connection); } diff --git a/src/ipconfig.c b/src/ipconfig.c index 90efb6a..dbf8f5a 100644 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -438,7 +438,7 @@ static void update_stats(struct connman_ipdevice *ipdevice, ipdevice->rx_dropped = stats->rx_dropped; ipdevice->tx_dropped = stats->tx_dropped; - __connman_counter_notify(ipdevice->config, + __connman_service_notify(ipdevice->config, ipdevice->rx_packets, ipdevice->tx_packets, ipdevice->rx_bytes, ipdevice->tx_bytes, ipdevice->rx_errors, ipdevice->tx_errors, diff --git a/src/service.c b/src/service.c index b22edb1..d387b75 100644 --- a/src/service.c +++ b/src/service.c @@ -35,40 +35,50 @@ static DBusConnection *connection = NULL; static GSequence *service_list = NULL; static GHashTable *service_hash = NULL; +static GSList *counter_list = NULL; struct connman_stats { connman_bool_t valid; connman_bool_t enabled; - unsigned int rx_packets_update; - unsigned int tx_packets_update; unsigned int rx_packets_last; unsigned int tx_packets_last; unsigned int rx_packets; unsigned int tx_packets; - unsigned int rx_bytes_update; - unsigned int tx_bytes_update; unsigned int rx_bytes_last; unsigned int tx_bytes_last; unsigned int rx_bytes; unsigned int tx_bytes; - unsigned int rx_errors_update; - unsigned int tx_errors_update; unsigned int rx_errors_last; unsigned int tx_errors_last; unsigned int rx_errors; unsigned int tx_errors; - unsigned int rx_dropped_update; - unsigned int tx_dropped_update; unsigned int rx_dropped_last; unsigned int tx_dropped_last; unsigned int rx_dropped; unsigned int tx_dropped; unsigned int time_start; - unsigned int time_update; unsigned int time; GTimer *timer; }; +struct connman_stats_update { + unsigned int rx_packets; + unsigned int tx_packets; + unsigned int rx_bytes; + unsigned int tx_bytes; + unsigned int rx_errors; + unsigned int tx_errors; + unsigned int rx_dropped; + unsigned int tx_dropped; + unsigned int time; +}; + +struct connman_stats_counter { + connman_bool_t append_all; + struct connman_stats_update stats; + struct connman_stats_update stats_roaming; +}; + struct connman_service { gint refcount; char *identifier; @@ -117,6 +127,7 @@ struct connman_service { struct connman_location *location; struct connman_stats stats; struct connman_stats stats_roaming; + GHashTable *counter_table; }; static void append_path(gpointer value, gpointer user_data) @@ -468,8 +479,6 @@ static void stats_start(struct connman_service *service) stats->time_start = stats->time; g_timer_start(stats->timer); - - __connman_counter_add_service(service); } static void stats_stop(struct connman_service *service) @@ -485,8 +494,6 @@ static void stats_stop(struct connman_service *service) if (stats->enabled == FALSE) return; - __connman_counter_remove_service(service); - g_timer_stop(stats->timer); seconds = g_timer_elapsed(stats->timer, NULL); @@ -603,16 +610,6 @@ static void reset_stats(struct connman_service *service) service->stats.time = 0; service->stats.time_start = 0; - service->stats.rx_packets_update = 0; - service->stats.tx_packets_update = 0; - service->stats.rx_bytes_update = 0; - service->stats.tx_bytes_update = 0; - service->stats.rx_errors_update = 0; - service->stats.tx_errors_update = 0; - service->stats.rx_dropped_update = 0; - service->stats.tx_dropped_update = 0; - service->stats.time_update = 0; - g_timer_reset(service->stats.timer); /* roaming */ @@ -629,16 +626,6 @@ static void reset_stats(struct connman_service *service) service->stats_roaming.time = 0; service->stats_roaming.time_start = 0; - service->stats_roaming.rx_packets_update = 0; - service->stats_roaming.tx_packets_update = 0; - service->stats_roaming.rx_bytes_update = 0; - service->stats_roaming.tx_bytes_update = 0; - service->stats_roaming.rx_errors_update = 0; - service->stats_roaming.tx_errors_update = 0; - service->stats_roaming.rx_dropped_update = 0; - service->stats_roaming.tx_dropped_update = 0; - service->stats_roaming.time_update = 0; - g_timer_reset(service->stats_roaming.timer); } @@ -1054,86 +1041,232 @@ static void link_changed(struct connman_service *service) append_ethernet, service); } -static void stats_append(DBusMessageIter *dict, +static void stats_append_counters(DBusMessageIter *dict, struct connman_stats *stats, + struct connman_stats_update *counters, connman_bool_t append_all) { - if (stats->rx_packets_update != stats->rx_packets || append_all) { - stats->rx_packets_update = stats->rx_packets; + if (counters->rx_packets != stats->rx_packets || append_all) { + counters->rx_packets = stats->rx_packets; connman_dbus_dict_append_basic(dict, "RX.Packets", DBUS_TYPE_UINT32, &stats->rx_packets); } - if (stats->tx_packets_update != stats->tx_packets || append_all) { - stats->tx_packets_update = stats->tx_packets; + if (counters->tx_packets != stats->tx_packets || append_all) { + counters->tx_packets = stats->tx_packets; connman_dbus_dict_append_basic(dict, "TX.Packets", DBUS_TYPE_UINT32, &stats->tx_packets); } - if (stats->rx_bytes_update != stats->rx_bytes || append_all) { - stats->rx_bytes_update = stats->rx_bytes; + if (counters->rx_bytes != stats->rx_bytes || append_all) { + counters->rx_bytes = stats->rx_bytes; connman_dbus_dict_append_basic(dict, "RX.Bytes", DBUS_TYPE_UINT32, &stats->rx_bytes); } - if (stats->tx_bytes_update != stats->tx_bytes || append_all) { - stats->tx_bytes_update = stats->tx_bytes; + if (counters->tx_bytes != stats->tx_bytes || append_all) { + counters->tx_bytes = stats->tx_bytes; connman_dbus_dict_append_basic(dict, "TX.Bytes", DBUS_TYPE_UINT32, &stats->tx_bytes); } - if (stats->rx_errors_update != stats->rx_errors || append_all) { - stats->rx_errors_update = stats->rx_errors; + if (counters->rx_errors != stats->rx_errors || append_all) { + counters->rx_errors = stats->rx_errors; connman_dbus_dict_append_basic(dict, "RX.Errors", DBUS_TYPE_UINT32, &stats->rx_errors); } - if (stats->tx_errors_update != stats->tx_errors || append_all) { - stats->tx_errors_update = stats->tx_errors; + if (counters->tx_errors != stats->tx_errors || append_all) { + counters->tx_errors = stats->tx_errors; connman_dbus_dict_append_basic(dict, "TX.Errors", DBUS_TYPE_UINT32, &stats->tx_errors); } - if (stats->rx_dropped_update != stats->rx_dropped || append_all) { - stats->rx_dropped_update = stats->rx_dropped; + if (counters->rx_dropped != stats->rx_dropped || append_all) { + counters->rx_dropped = stats->rx_dropped; connman_dbus_dict_append_basic(dict, "RX.Dropped", DBUS_TYPE_UINT32, &stats->rx_dropped); } - if (stats->tx_dropped_update != stats->tx_dropped || append_all) { - stats->tx_dropped_update = stats->tx_dropped; + if (counters->tx_dropped != stats->tx_dropped || append_all) { + counters->tx_dropped = stats->tx_dropped; connman_dbus_dict_append_basic(dict, "TX.Dropped", DBUS_TYPE_UINT32, &stats->tx_dropped); } - if (stats->time_update != stats->time || append_all) { - stats->time_update = stats->time; + if (counters->time != stats->time || append_all) { + counters->time = stats->time; connman_dbus_dict_append_basic(dict, "Time", DBUS_TYPE_UINT32, &stats->time); } } -void __connman_service_stats_append(struct connman_service *service, - DBusMessage *msg, - connman_bool_t append_all) +static void stats_append(struct connman_service *service, + const char *counter, + struct connman_stats_counter *counters, + connman_bool_t append_all) { DBusMessageIter array, dict; + DBusMessage *msg; + + DBG("service %p counter %s", service, counter); + + msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL); + if (msg == NULL) + return; + + dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, + &service->path, DBUS_TYPE_INVALID); dbus_message_iter_init_append(msg, &array); /* home counter */ connman_dbus_dict_open(&array, &dict); - stats_append(&dict, &service->stats, append_all); + stats_append_counters(&dict, &service->stats, + &counters->stats, append_all); connman_dbus_dict_close(&array, &dict); /* roaming counter */ connman_dbus_dict_open(&array, &dict); - stats_append(&dict, &service->stats_roaming, append_all); + stats_append_counters(&dict, &service->stats_roaming, + &counters->stats_roaming, append_all); connman_dbus_dict_close(&array, &dict); + + __connman_counter_send_usage(counter, msg); +} + +static void stats_update(struct connman_service *service, + unsigned int rx_packets, unsigned int tx_packets, + unsigned int rx_bytes, unsigned int tx_bytes, + unsigned int rx_errors, unsigned int tx_errors, + unsigned int rx_dropped, unsigned int tx_dropped) +{ + struct connman_stats *stats = stats_get(service); + unsigned int seconds; + + DBG("service %p", service); + + if (stats->valid == TRUE) { + stats->rx_packets += + rx_packets - stats->rx_packets_last; + stats->tx_packets += + tx_packets - stats->tx_packets_last; + stats->rx_bytes += + rx_bytes - stats->rx_bytes_last; + stats->tx_bytes += + tx_bytes - stats->tx_bytes_last; + stats->rx_errors += + rx_errors - stats->rx_errors_last; + stats->tx_errors += + tx_errors - stats->tx_errors_last; + stats->rx_dropped += + rx_dropped - stats->rx_dropped_last; + stats->tx_dropped += + tx_dropped - stats->tx_dropped_last; + } else { + stats->valid = TRUE; + } + + stats->rx_packets_last = rx_packets; + stats->tx_packets_last = tx_packets; + stats->rx_bytes_last = rx_bytes; + stats->tx_bytes_last = tx_bytes; + stats->rx_errors_last = rx_errors; + stats->tx_errors_last = tx_errors; + stats->rx_dropped_last = rx_dropped; + stats->tx_dropped_last = tx_dropped; + + seconds = g_timer_elapsed(stats->timer, NULL); + stats->time = stats->time_start + seconds; +} + +void __connman_service_notify(struct connman_ipconfig *ipconfig, + unsigned int rx_packets, unsigned int tx_packets, + unsigned int rx_bytes, unsigned int tx_bytes, + unsigned int rx_errors, unsigned int tx_errors, + unsigned int rx_dropped, unsigned int tx_dropped) +{ + struct connman_service *service; + GHashTableIter iter; + gpointer key, value; + const char *counter; + struct connman_stats_counter *counters; + + service = connman_ipconfig_get_data(ipconfig); + if (service == NULL) + return; + + if (is_connected(service) == FALSE) + return; + + stats_update(service, + rx_packets, tx_packets, + rx_bytes, tx_bytes, + rx_errors, tx_errors, + rx_dropped, tx_dropped); + + g_hash_table_iter_init(&iter, service->counter_table); + while (g_hash_table_iter_next(&iter, &key, &value)) { + counter = key; + counters = value; + + stats_append(service, counter, counters, counters->append_all); + counters->append_all = FALSE; + } +} + +int __connman_service_counter_register(const char *counter) +{ + struct connman_service *service = NULL; + GSequenceIter *iter; + struct connman_stats_counter *counters; + + DBG("counter %s", counter); + + counter_list = g_slist_append(counter_list, (gpointer)counter); + + iter = g_sequence_get_begin_iter(service_list); + + while (g_sequence_iter_is_end(iter) == FALSE) { + service = g_sequence_get(iter); + + counters = g_try_new0(struct connman_stats_counter, 1); + if (counters == NULL) + return -ENOMEM; + + counters->append_all = TRUE; + + g_hash_table_replace(service->counter_table, (gpointer)counter, + counters); + + iter = g_sequence_iter_next(iter); + } + + return 0; +} + +void __connman_service_counter_unregister(const char *counter) +{ + struct connman_service *service = NULL; + GSequenceIter *iter; + + DBG("counter %s", counter); + + iter = g_sequence_get_begin_iter(service_list); + + while (g_sequence_iter_is_end(iter) == FALSE) { + service = g_sequence_get(iter); + + g_hash_table_remove(service->counter_table, counter); + + iter = g_sequence_iter_next(iter); + } + + counter_list = g_slist_remove(counter_list, counter); } static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, @@ -2016,6 +2149,8 @@ static DBusMessage *remove_service(DBusConnection *conn, __connman_network_disconnect(service->network); } + g_hash_table_destroy(service->counter_table); + g_free(service->passphrase); service->passphrase = NULL; @@ -2261,6 +2396,10 @@ static void service_initialize(struct connman_service *service) */ struct connman_service *connman_service_create(void) { + GSList *list; + struct connman_stats_counter *counters; + const char *counter; + struct connman_service *service; service = g_try_new0(struct connman_service, 1); @@ -2269,6 +2408,25 @@ struct connman_service *connman_service_create(void) DBG("service %p", service); + service->counter_table = g_hash_table_new_full(g_str_hash, + g_str_equal, NULL, g_free); + + for (list = counter_list; list; list = list->next) { + counter = list->data; + + counters = g_try_new0(struct connman_stats_counter, 1); + if (counters == NULL) { + g_hash_table_destroy(service->counter_table); + g_free(service); + return NULL; + } + + counters->append_all = TRUE; + + g_hash_table_replace(service->counter_table, (gpointer)counter, + counters); + } + service_initialize(service); service->location = __connman_location_create(service); @@ -3717,57 +3875,6 @@ __connman_service_create_from_provider(struct connman_provider *provider) return service; } -connman_bool_t __connman_service_stats_update(struct connman_service *service, - unsigned int rx_packets, unsigned int tx_packets, - unsigned int rx_bytes, unsigned int tx_bytes, - unsigned int rx_errors, unsigned int tx_errors, - unsigned int rx_dropped, unsigned int tx_dropped) -{ - unsigned int seconds; - struct connman_stats *stats = stats_get(service); - gboolean valid = stats->valid; - - DBG("service %p", service); - - if (is_connected(service) == FALSE) - return valid; - - if (valid == TRUE) { - stats->rx_packets += - rx_packets - stats->rx_packets_last; - stats->tx_packets += - tx_packets - stats->tx_packets_last; - stats->rx_bytes += - rx_bytes - stats->rx_bytes_last; - stats->tx_bytes += - tx_bytes - stats->tx_bytes_last; - stats->rx_errors += - rx_errors - stats->rx_errors_last; - stats->tx_errors += - tx_errors - stats->tx_errors_last; - stats->rx_dropped += - rx_dropped - stats->rx_dropped_last; - stats->tx_dropped += - tx_dropped - stats->tx_dropped_last; - } else { - stats->valid = TRUE; - } - - stats->rx_packets_last = rx_packets; - stats->tx_packets_last = tx_packets; - stats->rx_bytes_last = rx_bytes; - stats->tx_bytes_last = tx_bytes; - stats->rx_errors_last = rx_errors; - stats->tx_errors_last = tx_errors; - stats->rx_dropped_last = rx_dropped; - stats->tx_dropped_last = tx_dropped; - - seconds = g_timer_elapsed(stats->timer, NULL); - stats->time = stats->time_start + seconds; - - return valid; -} - static int service_load(struct connman_service *service) { const char *ident = service->profile; @@ -4147,6 +4254,9 @@ void __connman_service_cleanup(void) g_hash_table_destroy(service_hash); service_hash = NULL; + g_slist_free(counter_list); + counter_list = NULL; + connman_storage_unregister(&service_storage); dbus_connection_unref(connection); -- 2.7.4