base-bearer: setup periodic stats loading

If the bearer implementation supports it, load stats periodically. By default
every 30s for now.
This commit is contained in:
Aleksander Morgado
2015-11-27 14:30:00 +01:00
parent 810e52c6db
commit 3bf118d01a
2 changed files with 133 additions and 6 deletions

View File

@@ -13,7 +13,8 @@
* Copyright (C) 2008 - 2009 Novell, Inc. * Copyright (C) 2008 - 2009 Novell, Inc.
* Copyright (C) 2009 - 2011 Red Hat, Inc. * Copyright (C) 2009 - 2011 Red Hat, Inc.
* Copyright (C) 2011 Google, Inc. * Copyright (C) 2011 Google, Inc.
* Copyright (C) 2011 - 2014 Aleksander Morgado <aleksander@aleksander.es> * Copyright (C) 2015 Azimut Electronics
* Copyright (C) 2011 - 2015 Aleksander Morgado <aleksander@aleksander.es>
*/ */
#include <config.h> #include <config.h>
@@ -36,13 +37,16 @@
#include "mm-base-modem.h" #include "mm-base-modem.h"
#include "mm-log.h" #include "mm-log.h"
#include "mm-modem-helpers.h" #include "mm-modem-helpers.h"
#include "mm-bearer-stats.h"
/* We require up to 20s to get a proper IP when using PPP */ /* We require up to 20s to get a proper IP when using PPP */
#define BEARER_IP_TIMEOUT_DEFAULT 20 #define BEARER_IP_TIMEOUT_DEFAULT 20
#define BEARER_DEFERRED_UNREGISTRATION_TIMEOUT 15 #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 { typedef enum {
CONNECTION_FORBIDDEN_REASON_NONE, CONNECTION_FORBIDDEN_REASON_NONE,
@@ -97,6 +101,13 @@ struct _MMBaseBearerPrivate {
/* Handler IDs for the registration state change signals */ /* Handler IDs for the registration state change signals */
guint id_cdma1x_registration_change; guint id_cdma1x_registration_change;
guint id_evdo_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;
}; };
/*****************************************************************************/ /*****************************************************************************/
@@ -124,6 +135,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 rx_bytes = 0;
guint64 tx_bytes = 0;
if (!MM_BASE_BEARER_GET_CLASS (self)->reload_stats_finish (self, &rx_bytes, &tx_bytes, 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_tx_bytes (self->priv->stats, rx_bytes);
mm_bearer_stats_set_rx_bytes (self->priv->stats, tx_bytes);
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 G_SOURCE_CONTINUE;
}
/* 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_tx_bytes (self->priv->stats, 0);
mm_bearer_stats_set_rx_bytes (self->priv->stats, 0);
bearer_update_interface_stats (self);
return G_SOURCE_CONTINUE;
}
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 static void
bearer_reset_interface_status (MMBaseBearer *self) bearer_reset_interface_status (MMBaseBearer *self)
{ {
@@ -151,8 +258,11 @@ bearer_update_status (MMBaseBearer *self,
/* Ensure that we don't expose any connection related data in the /* Ensure that we don't expose any connection related data in the
* interface when going into disconnected state. */ * 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); bearer_reset_interface_status (self);
/* Stop statistics */
bearer_stats_stop (self);
}
} }
static void static void
@@ -171,6 +281,9 @@ bearer_update_status_connected (MMBaseBearer *self,
MM_GDBUS_BEARER (self), MM_GDBUS_BEARER (self),
mm_bearer_ip_config_get_dictionary (ipv6_config)); mm_bearer_ip_config_get_dictionary (ipv6_config));
/* Start statistics */
bearer_stats_start (self);
/* Update the property value */ /* Update the property value */
self->priv->status = MM_BEARER_STATUS_CONNECTED; self->priv->status = MM_BEARER_STATUS_CONNECTED;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATUS]); 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); mm_dbg ("Connecting bearer '%s'", self->priv->path);
self->priv->connect_cancellable = g_cancellable_new (); self->priv->connect_cancellable = g_cancellable_new ();
bearer_update_status (self, MM_BEARER_STATUS_CONNECTING); bearer_update_status (self, MM_BEARER_STATUS_CONNECTING);
bearer_reset_interface_stats (self);
MM_BASE_BEARER_GET_CLASS (self)->connect ( MM_BASE_BEARER_GET_CLASS (self)->connect (
self, self,
self->priv->connect_cancellable, self->priv->connect_cancellable,
@@ -1150,6 +1264,9 @@ dispose (GObject *object)
{ {
MMBaseBearer *self = MM_BASE_BEARER (object); MMBaseBearer *self = MM_BASE_BEARER (object);
bearer_stats_stop (self);
g_clear_object (&self->priv->stats);
if (self->priv->connection) { if (self->priv->connection) {
base_bearer_dbus_unexport (self); base_bearer_dbus_unexport (self);
g_clear_object (&self->priv->connection); g_clear_object (&self->priv->connection);

View File

@@ -10,10 +10,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details: * GNU General Public License for more details:
* *
* Author: Aleksander Morgado <aleksander@lanedo.com>
*
* Copyright (C) 2011 Google, Inc. * Copyright (C) 2011 Google, Inc.
* Copyright (C) 2011 - 2013 Aleksander Morgado <aleksander@gnu.org> * Copyright (C) 2015 Azimut Electronics
* Copyright (C) 2011 - 2015 Aleksander Morgado <aleksander@aleksander.es>
*/ */
#ifndef MM_BASE_BEARER_H #ifndef MM_BASE_BEARER_H
@@ -101,6 +101,16 @@ struct _MMBaseBearerClass {
GAsyncResult *res, GAsyncResult *res,
GError **error); 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 */ /* Report connection status of this bearer */
void (* report_connection_status) (MMBaseBearer *bearer, void (* report_connection_status) (MMBaseBearer *bearer,
MMBearerConnectionStatus status); MMBearerConnectionStatus status);