On Fri, 2015-11-27 at 14:51 +0100, Aleksander Morgado wrote: > If the bearer implementation supports it, load stats periodically. By > default > every 30s for now. > --- > src/mm-base-bearer.c | 123 > +++++++++++++++++++++++++++++++++++++++++++++++++-- > src/mm-base-bearer.h | 16 +++++-- > 2 files changed, 133 insertions(+), 6 deletions(-) > > diff --git a/src/mm-base-bearer.c b/src/mm-base-bearer.c > index 1b1c7b3..117f144 100644 > --- a/src/mm-base-bearer.c > +++ b/src/mm-base-bearer.c > @@ -13,7 +13,8 @@ > * Copyright (C) 2008 - 2009 Novell, Inc. > * Copyright (C) 2009 - 2011 Red Hat, Inc. > * Copyright (C) 2011 Google, Inc. > - * Copyright (C) 2011 - 2014 Aleksander Morgado < > aleksan...@aleksander.es> > + * Copyright (C) 2015 Azimut Electronics > + * Copyright (C) 2011 - 2015 Aleksander Morgado < > aleksan...@aleksander.es> > */ > > #include <config.h> > @@ -36,13 +37,16 @@ > #include "mm-base-modem.h" > #include "mm-log.h" > #include "mm-modem-helpers.h" > +#include "mm-bearer-stats.h" > > /* We require up to 20s to get a proper IP when using PPP */ > #define BEARER_IP_TIMEOUT_DEFAULT 20 > > #define BEARER_DEFERRED_UNREGISTRATION_TIMEOUT 15 > > -G_DEFINE_TYPE (MMBaseBearer, mm_base_bearer, > MM_GDBUS_TYPE_BEARER_SKELETON); > +#define BEARER_STATS_UPDATE_TIMEOUT 30 > + > +G_DEFINE_TYPE (MMBaseBearer, mm_base_bearer, > MM_GDBUS_TYPE_BEARER_SKELETON) > > typedef enum { > CONNECTION_FORBIDDEN_REASON_NONE, > @@ -97,6 +101,13 @@ struct _MMBaseBearerPrivate { > /* Handler IDs for the registration state change signals */ > guint id_cdma1x_registration_change; > guint id_evdo_registration_change; > + > + /* The stats object to expose */ > + MMBearerStats *stats; > + /* Handler id for the stats update timeout */ > + guint stats_update_id; > + /* Timer to measure the duration of the connection */ > + GTimer *duration_timer; > }; > > /******************************************************************* > **********/ > @@ -125,6 +136,102 @@ mm_base_bearer_export (MMBaseBearer *self) > /******************************************************************* > **********/ > > static void > +bearer_update_interface_stats (MMBaseBearer *self) > +{ > + mm_gdbus_bearer_set_stats ( > + MM_GDBUS_BEARER (self), > + mm_bearer_stats_get_dictionary (self->priv->stats)); > +} > + > +static void > +bearer_reset_interface_stats (MMBaseBearer *self) > +{ > + g_clear_object (&self->priv->stats); > + mm_gdbus_bearer_set_stats (MM_GDBUS_BEARER (self), NULL); > +} > + > +static void > +bearer_stats_stop (MMBaseBearer *self) > +{ > + if (self->priv->duration_timer) { > + if (self->priv->stats) > + mm_bearer_stats_set_duration (self->priv->stats, > (guint64) g_timer_elapsed (self->priv->duration_timer, NULL)); > + g_timer_destroy (self->priv->duration_timer); > + self->priv->duration_timer = NULL; > + } > + > + if (self->priv->stats_update_id) { > + g_source_remove (self->priv->stats_update_id); > + self->priv->stats_update_id = 0; > + } > +} > + > +static void > +reload_stats_ready (MMBaseBearer *self, > + GAsyncResult *res) > +{ > + GError *error = NULL; > + guint64 bytes_rx = 0; > + guint64 bytes_tx = 0; > + > + if (!MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish (self, > &bytes_rx, &bytes_tx, res, &error)) { > + g_warning ("Reloading stats failed: %s", error->message); > + g_error_free (error); > + return; > + } > + > + /* We only update stats if they were retrieved properly */ > + mm_bearer_stats_set_duration (self->priv->stats, (guint32) > g_timer_elapsed (self->priv->duration_timer, NULL)); > + mm_bearer_stats_set_bytes_tx (self->priv->stats, bytes_rx); > + mm_bearer_stats_set_bytes_rx (self->priv->stats, bytes_tx); > + bearer_update_interface_stats (self); > +} > + > +static gboolean > +stats_update_cb (MMBaseBearer *self) > +{ > + /* If the implementation knows how to update stat values, run it > */ > + if (MM_BASE_BEARER_GET_CLASS (self)->reload_stats && > + MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish) { > + MM_BASE_BEARER_GET_CLASS (self)->reload_stats ( > + self, > + (GAsyncReadyCallback)reload_stats_ready, > + NULL); > + return TRUE; > + } > + > + /* Otherwise, just update duration and we're done */ > + mm_bearer_stats_set_duration (self->priv->stats, (guint32) > g_timer_elapsed (self->priv->duration_timer, NULL)); > + mm_bearer_stats_set_bytes_tx (self->priv->stats, 0); > + mm_bearer_stats_set_bytes_rx (self->priv->stats, 0); > + bearer_update_interface_stats (self); > + return TRUE; > I'm a fan of G_SOURCE_CONTINUE/G_SOURCE_REMOVE these days, but that's personal preference.
Dan > +} > + > +static void > +bearer_stats_start (MMBaseBearer *self) > +{ > + /* Allocate new stats object. If there was one already created > from a > + * previous run, deallocate it */ > + g_assert (!self->priv->stats); > + self->priv->stats = mm_bearer_stats_new (); > + > + /* Start duration timer */ > + g_assert (!self->priv->duration_timer); > + self->priv->duration_timer = g_timer_new (); > + > + /* Schedule */ > + g_assert (!self->priv->stats_update_id); > + self->priv->stats_update_id = g_timeout_add_seconds > (BEARER_STATS_UPDATE_TIMEOUT, > + > (GSourceFunc) stats_update_cb, > + self); > + /* Load initial values */ > + stats_update_cb (self); > +} > + > +/******************************************************************* > **********/ > + > +static void > bearer_reset_interface_status (MMBaseBearer *self) > { > mm_gdbus_bearer_set_connected (MM_GDBUS_BEARER (self), FALSE); > @@ -151,8 +258,11 @@ bearer_update_status (MMBaseBearer *self, > > /* Ensure that we don't expose any connection related data in > the > * interface when going into disconnected state. */ > - if (self->priv->status == MM_BEARER_STATUS_DISCONNECTED) > + if (self->priv->status == MM_BEARER_STATUS_DISCONNECTED) { > bearer_reset_interface_status (self); > + /* Stop statistics */ > + bearer_stats_stop (self); > + } > } > > static void > @@ -171,6 +281,9 @@ bearer_update_status_connected (MMBaseBearer > *self, > MM_GDBUS_BEARER (self), > mm_bearer_ip_config_get_dictionary (ipv6_config)); > > + /* Start statistics */ > + bearer_stats_start (self); > + > /* Update the property value */ > self->priv->status = MM_BEARER_STATUS_CONNECTED; > g_object_notify_by_pspec (G_OBJECT (self), > properties[PROP_STATUS]); > @@ -590,6 +703,7 @@ mm_base_bearer_connect (MMBaseBearer *self, > mm_dbg ("Connecting bearer '%s'", self->priv->path); > self->priv->connect_cancellable = g_cancellable_new (); > bearer_update_status (self, MM_BEARER_STATUS_CONNECTING); > + bearer_reset_interface_stats (self); > MM_BASE_BEARER_GET_CLASS (self)->connect ( > self, > self->priv->connect_cancellable, > @@ -1150,6 +1264,9 @@ dispose (GObject *object) > { > MMBaseBearer *self = MM_BASE_BEARER (object); > > + bearer_stats_stop (self); > + g_clear_object (&self->priv->stats); > + > if (self->priv->connection) { > base_bearer_dbus_unexport (self); > g_clear_object (&self->priv->connection); > diff --git a/src/mm-base-bearer.h b/src/mm-base-bearer.h > index 2c196f6..58954d4 100644 > --- a/src/mm-base-bearer.h > +++ b/src/mm-base-bearer.h > @@ -10,10 +10,10 @@ > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > * GNU General Public License for more details: > * > - * Author: Aleksander Morgado <aleksan...@lanedo.com> > - * > + > * Copyright (C) 2011 Google, Inc. > - * Copyright (C) 2011 - 2013 Aleksander Morgado <aleksan...@gnu.org> > + * Copyright (C) 2015 Azimut Electronics > + * Copyright (C) 2011 - 2015 Aleksander Morgado < > aleksan...@aleksander.es> > */ > > #ifndef MM_BASE_BEARER_H > @@ -101,6 +101,16 @@ struct _MMBaseBearerClass { > GAsyncResult *res, > GError **error); > > + /* Reload statistics */ > + void (* reload_stats) (MMBaseBearer *bearer, > + GAsyncReadyCallback callback, > + gpointer user_data); > + gboolean (* reload_stats_finish) (MMBaseBearer *bearer, > + guint64 *bytes_rx, > + guint64 *bytes_tx, > + GAsyncResult *res, > + GError **error); > + > /* Report connection status of this bearer */ > void (* report_connection_status) (MMBaseBearer *bearer, > MMBearerConnectionStatus > status); _______________________________________________ ModemManager-devel mailing list ModemManager-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/modemmanager-devel