From: Daniel Wagner <[email protected]>
The static values are maintained in the
Service object and exposed through simple
accessors.
When a Service object enters the ready state it
registers itself at Counter with a default
interval timeout for updates of 10 seconds.
If the Service object is leaving the ready
state it will de-register itself from Counter
and consequently it will not be updated
anymore.
The user can shorten the update interval
when he registers a Counter object with
a shorter interval value.
The statistic is stored in the profile file.
Only the current value is stored, no history.
---
src/connman.h | 10 +++
src/service.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 184 insertions(+), 0 deletions(-)
diff --git a/src/connman.h b/src/connman.h
index 8bf5e97..c30dccd 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -435,6 +435,16 @@ void __connman_service_append_nameserver(struct
connman_service *service,
void __connman_service_remove_nameserver(struct connman_service *service,
const char *nameserver);
+unsigned long __connman_service_stats_get_tx_bytes(
+ struct connman_service *service);
+unsigned long __connman_service_stats_get_rx_bytes(
+ struct connman_service *service);
+unsigned long __connman_service_stats_get_time(
+ struct connman_service *service);
+void __connman_service_stats_update(struct connman_service *service,
+ unsigned long rx_bytes,
+ unsigned long tx_bytes);
+
#include <connman/location.h>
int __connman_location_init(void);
diff --git a/src/service.c b/src/service.c
index 4d0afc5..e0700ce 100644
--- a/src/service.c
+++ b/src/service.c
@@ -36,6 +36,17 @@ static DBusConnection *connection = NULL;
static GSequence *service_list = NULL;
static GHashTable *service_hash = NULL;
+struct connman_service_statistics {
+ connman_bool_t valid;
+ unsigned int rx_bytes_last;
+ unsigned int tx_bytes_last;
+ unsigned int rx_bytes;
+ unsigned int tx_bytes;
+ unsigned int time_start;
+ unsigned int time;
+ GTimer *timer;
+};
+
struct connman_service {
gint refcount;
char *identifier;
@@ -79,6 +90,7 @@ struct connman_service {
DBusMessage *pending;
guint timeout;
struct connman_location *location;
+ struct connman_service_statistics stats;
};
static void append_path(gpointer value, gpointer user_data)
@@ -349,6 +361,106 @@ void __connman_service_remove_nameserver(struct
connman_service *service,
update_nameservers(service);
}
+static void __connman_service_stats_start(struct connman_service *service)
+{
+ DBG("service %p", service);
+
+ if (service->stats.timer == NULL)
+ return;
+
+ service->stats.time_start = service->stats.time;
+
+ g_timer_start(service->stats.timer);
+}
+
+static void __connman_service_stats_stop(struct connman_service *service)
+{
+ uint32_t seconds;
+
+ DBG("service %p", service);
+
+ if (service->stats.timer == NULL)
+ return;
+
+ g_timer_stop(service->stats.timer);
+
+ seconds = (uint32_t)g_timer_elapsed(service->stats.timer, NULL);
+ service->stats.time = service->stats.time_start + seconds;
+}
+
+static int __connman_service_stats_load(struct connman_service *service,
+ GKeyFile *keyfile, const char *identifier, const char *prefix)
+{
+ char *key;
+
+ key = g_strdup_printf("%srx_bytes", prefix);
+ service->stats.rx_bytes = g_key_file_get_integer(keyfile,
+ identifier, key, NULL);
+ g_free(key);
+
+ key = g_strdup_printf("%stx_bytes", prefix);
+ service->stats.tx_bytes = g_key_file_get_integer(keyfile,
+ identifier, key, NULL);
+ g_free(key);
+
+ key = g_strdup_printf("%stime", prefix);
+ service->stats.time = g_key_file_get_integer(keyfile,
+ identifier, key, NULL);
+ g_free(key);
+
+ return 0;
+}
+
+static int __connman_service_stats_save(struct connman_service *service,
+ GKeyFile *keyfile, const char *identifier, const char *prefix)
+{
+ char *key;
+
+ key = g_strdup_printf("%srx_bytes", prefix);
+ g_key_file_set_integer(keyfile, identifier, key,
+ service->stats.rx_bytes);
+ g_free(key);
+
+ key = g_strdup_printf("%stx_bytes", prefix);
+ g_key_file_set_integer(keyfile, identifier, key,
+ service->stats.tx_bytes);
+ g_free(key);
+
+ key = g_strdup_printf("%stime", prefix);
+ g_key_file_set_integer(keyfile, identifier, key,
+ service->stats.time);
+ g_free(key);
+
+ return 0;
+}
+
+static void __connman_service_reset_stats(struct connman_service *service)
+{
+ service->stats.valid = FALSE;
+ service->stats.rx_bytes = 0;
+ service->stats.tx_bytes = 0;
+ service->stats.time = 0;
+ service->stats.time_start = 0;
+ g_timer_reset(service->stats.timer);
+
+}
+unsigned long __connman_service_stats_get_tx_bytes(
+ struct connman_service *service)
+{
+ return service->stats.tx_bytes;
+}
+unsigned long __connman_service_stats_get_rx_bytes(
+ struct connman_service *service)
+{
+ return service->stats.rx_bytes;
+}
+
+unsigned long __connman_service_stats_get_time(
+ struct connman_service *service)
+{
+ return service->stats.time;
+}
+
static struct connman_service *get_default(void)
{
struct connman_service *service;
@@ -1536,6 +1648,18 @@ static DBusMessage *move_after(DBusConnection *conn,
return move_service(conn, msg, user_data, FALSE);
}
+static DBusMessage *reset_stats(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ struct connman_service *service = user_data;
+
+ DBG("service %p", service);
+
+ __connman_service_reset_stats(service);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
static GDBusMethodTable service_methods[] = {
{ "GetProperties", "", "a{sv}", get_properties },
{ "SetProperty", "sv", "", set_property },
@@ -1546,6 +1670,7 @@ static GDBusMethodTable service_methods[] = {
{ "Remove", "", "", remove_service },
{ "MoveBefore", "o", "", move_before },
{ "MoveAfter", "o", "", move_after },
+ { "ResetStatistics", "", "", reset_stats },
{ },
};
@@ -1606,6 +1731,10 @@ static void service_free(gpointer user_data)
g_free(service->private_key_file);
g_free(service->private_key_passphrase);
g_free(service->phase2);
+
+ if (service->stats.timer != NULL)
+ g_timer_destroy(service->stats.timer);
+
g_free(service);
}
@@ -1654,6 +1783,9 @@ static void __connman_service_initialize(struct
connman_service *service)
service->userconnect = FALSE;
service->order = 0;
+
+ service->stats.valid = FALSE;
+ service->stats.timer = g_timer_new();
}
/**
@@ -1947,6 +2079,8 @@ int __connman_service_indicate_state(struct
connman_service *service,
__connman_notifier_connect(service->type);
+ __connman_service_stats_start(service);
+
default_changed();
} else if (state == CONNMAN_SERVICE_STATE_DISCONNECT) {
__connman_location_finish(service);
@@ -1957,6 +2091,9 @@ int __connman_service_indicate_state(struct
connman_service *service,
dns_changed(service);
__connman_notifier_disconnect(service->type);
+
+ __connman_service_stats_stop(service);
+ __connman_storage_save_service(service);
}
if (state == CONNMAN_SERVICE_STATE_FAILURE) {
@@ -2505,7 +2642,11 @@ static int service_register(struct connman_service
*service)
static void service_up(struct connman_ipconfig *ipconfig)
{
+ struct connman_service *service = connman_ipconfig_get_data(ipconfig);
+
connman_info("%s up", connman_ipconfig_get_ifname(ipconfig));
+
+ service->stats.valid = FALSE;
}
static void service_down(struct connman_ipconfig *ipconfig)
@@ -2943,6 +3084,34 @@ void __connman_service_remove_from_network(struct
connman_network *network)
__connman_service_put(service);
}
+void __connman_service_stats_update(struct connman_service *service,
+ unsigned long rx_bytes,
+ unsigned long tx_bytes)
+{
+ uint32_t seconds;
+ struct connman_service_statistics *stats = &service->stats;
+
+ DBG("service %p", service);
+
+ if (is_connected(service) == FALSE)
+ return;
+
+ if (stats->valid == TRUE) {
+ stats->rx_bytes +=
+ rx_bytes - stats->rx_bytes_last;
+ stats->tx_bytes +=
+ tx_bytes - stats->tx_bytes_last;
+ } else {
+ stats->valid = TRUE;
+ }
+
+ stats->rx_bytes_last = rx_bytes;
+ stats->tx_bytes_last = tx_bytes;
+
+ seconds = (uint32_t)g_timer_elapsed(stats->timer, NULL);
+ stats->time = stats->time_start + seconds;
+}
+
static int service_load(struct connman_service *service)
{
const char *ident = service->profile;
@@ -3100,6 +3269,8 @@ static int service_load(struct connman_service *service)
service->domains = NULL;
}
+ __connman_service_stats_load(service, keyfile,
+ service->identifier, "Stats.");
done:
g_key_file_free(keyfile);
@@ -3253,6 +3424,9 @@ update:
g_key_file_remove_key(keyfile, service->identifier,
"Domains", NULL);
+ __connman_service_stats_save(service, keyfile,
+ service->identifier, "Stats.");
+
data = g_key_file_to_data(keyfile, &length, NULL);
if (g_file_set_contents(pathname, data, length, NULL) == FALSE)
--
1.6.6.1
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman