summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/connman.h2
-rw-r--r--src/counter.c23
-rw-r--r--src/rtnl.c74
-rwxr-xr-xtest/test-counter9
4 files changed, 87 insertions, 21 deletions
diff --git a/src/connman.h b/src/connman.h
index 62113466..8bf5e970 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -490,6 +490,8 @@ int __connman_rtnl_init(void);
void __connman_rtnl_start(void);
void __connman_rtnl_cleanup(void);
+unsigned int __connman_rtnl_update_interval_add(unsigned int interval);
+unsigned int __connman_rtnl_update_interval_remove(unsigned int interval);
int __connman_rtnl_request_update(void);
int __connman_rtnl_send(const void *buf, size_t len);
diff --git a/src/counter.c b/src/counter.c
index d897fb59..bf9da902 100644
--- a/src/counter.c
+++ b/src/counter.c
@@ -42,7 +42,7 @@ struct connman_stats {
struct connman_counter {
char *owner;
char *path;
- guint timeout;
+ unsigned int interval;
guint watch;
};
@@ -63,8 +63,7 @@ static void remove_counter(gpointer user_data)
if (counter->watch > 0)
g_dbus_remove_watch(connection, counter->watch);
- if (counter->timeout > 0)
- g_source_remove(counter->timeout);
+ __connman_rtnl_update_interval_remove(counter->interval);
g_free(counter->owner);
g_free(counter->path);
@@ -81,17 +80,6 @@ static void owner_disconnect(DBusConnection *connection, void *user_data)
g_hash_table_remove(counter_table, counter->path);
}
-static gboolean counter_timeout(gpointer user_data)
-{
- struct connman_counter *counter = user_data;
-
- DBG("owner %s path %s", counter->owner, counter->path);
-
- __connman_rtnl_request_update();
-
- return TRUE;
-}
-
int __connman_counter_register(const char *owner, const char *path,
unsigned int interval)
{
@@ -113,15 +101,12 @@ int __connman_counter_register(const char *owner, const char *path,
g_hash_table_replace(counter_table, counter->path, counter);
g_hash_table_replace(owner_mapping, counter->owner, counter);
- if (interval > 0)
- counter->timeout = g_timeout_add_seconds(interval,
- counter_timeout, counter);
+ counter->interval = interval;
+ __connman_rtnl_update_interval_add(counter->interval);
counter->watch = g_dbus_add_disconnect_watch(connection, owner,
owner_disconnect, counter, NULL);
- __connman_rtnl_request_update();
-
return 0;
}
diff --git a/src/rtnl.c b/src/rtnl.c
index 9238dde0..2e0fca98 100644
--- a/src/rtnl.c
+++ b/src/rtnl.c
@@ -52,6 +52,10 @@ struct watch_data {
static GSList *watch_list = NULL;
static unsigned int watch_id = 0;
+static GSList *update_list = NULL;
+static guint update_interval = G_MAXUINT;
+static guint update_timeout = 0;
+
/**
* connman_rtnl_add_operstate_watch:
* @index: network device index
@@ -1073,6 +1077,73 @@ static int send_getroute(void)
return queue_request(req);
}
+static gboolean update_timeout_cb(gpointer user_data)
+{
+ __connman_rtnl_request_update();
+
+ return TRUE;
+}
+
+static void update_interval_callback(guint min)
+{
+ if (update_timeout > 0)
+ g_source_remove(update_timeout);
+
+ if (min < G_MAXUINT) {
+ update_interval = min;
+ update_timeout = g_timeout_add_seconds(update_interval,
+ update_timeout_cb, NULL);
+ } else {
+ update_timeout = 0;
+ update_interval = G_MAXUINT;
+ }
+}
+
+static gint compare_interval(gconstpointer a, gconstpointer b)
+{
+ guint val_a = GPOINTER_TO_UINT(a);
+ guint val_b = GPOINTER_TO_UINT(b);
+
+ return val_a - val_b;
+}
+
+unsigned int __connman_rtnl_update_interval_add(unsigned int interval)
+{
+ guint min;
+
+ if (interval == 0)
+ return 0;
+
+ update_list = g_slist_insert_sorted(update_list,
+ GUINT_TO_POINTER(interval), compare_interval);
+
+ min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
+ if (min < update_interval) {
+ update_interval_callback(min);
+ __connman_rtnl_request_update();
+ }
+
+ return update_interval;
+}
+
+unsigned int __connman_rtnl_update_interval_remove(unsigned int interval)
+{
+ guint min = G_MAXUINT;
+
+ if (interval == 0)
+ return 0;
+
+ update_list = g_slist_remove(update_list, GINT_TO_POINTER(interval));
+
+ if (update_list != NULL)
+ min = GPOINTER_TO_UINT(g_slist_nth_data(update_list, 0));
+
+ if (min > update_interval)
+ update_interval_callback(min);
+
+ return min;
+}
+
int __connman_rtnl_request_update(void)
{
return send_getlink();
@@ -1134,6 +1205,9 @@ void __connman_rtnl_cleanup(void)
g_slist_free(watch_list);
watch_list = NULL;
+ g_slist_free(update_list);
+ update_list = NULL;
+
for (list = request_list; list; list = list->next) {
struct rtnl_request *req = list->data;
diff --git a/test/test-counter b/test/test-counter
index 6a42885e..70a30273 100755
--- a/test/test-counter
+++ b/test/test-counter
@@ -1,5 +1,6 @@
#!/usr/bin/python
+import sys
import gobject
import dbus
@@ -30,10 +31,14 @@ if __name__ == '__main__':
manager = dbus.Interface(bus.get_object('org.moblin.connman', "/"),
'org.moblin.connman.Manager')
- path = "/test/counter"
+ interval = 2
+ if len(sys.argv) > 1:
+ interval = sys.argv[1]
+
+ path = "/test/counter%s" % interval
object = Counter(bus, path)
- manager.RegisterCounter(path, dbus.UInt32(2))
+ manager.RegisterCounter(path, dbus.UInt32(interval))
mainloop = gobject.MainLoop()
mainloop.run()