[PATCH 5/6] base-bearer: setup periodic stats loading

Dan Williams dcbw at redhat.com
Mon Nov 30 08:33:39 PST 2015


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 <
> aleksander at aleksander.es>
> + * Copyright (C) 2015 Azimut Electronics
> + * Copyright (C) 2011 - 2015 Aleksander Morgado <
> aleksander at 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 <aleksander at lanedo.com>
> - *
> +
>   * Copyright (C) 2011 Google, Inc.
> - * Copyright (C) 2011 - 2013 Aleksander Morgado <aleksander at gnu.org>
> + * Copyright (C) 2015 Azimut Electronics
> + * Copyright (C) 2011 - 2015 Aleksander Morgado <
> aleksander at 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);


More information about the ModemManager-devel mailing list