projects/package-update-indicator

changeset 31:9905d4ae351c

Fix continuos loop of update checks if the refresh cache interval is 0

If the interval for refreshing the cache is set to 0 each check for available
updates refreshes the cache and causes an "updates-changed" signal to be
emitted after a short delay which in turn triggers another check for updates.
The "updates-changed" signal does not actually mean that the number of
available updates has changed but rather that the package metadata cache has
been invalidated. Fix this by blocking the "updates-changed" signal handler
from when a periodic or irregular check is started until 4 seconds after it has
finished. This is necessary since the signal will be delivered with a delay
after a transaction has been completed.
In addition prevent checks for updates triggered by the "updates-changed"
signal from refreshing the cache even the interval is 0 since the emission of
the signal implies that the cache has just been refreshed.
author Guido Berhoerster <guido+pui@berhoerster.name>
date Thu Aug 29 13:48:47 2019 +0200 (9 months ago)
parents 811df672633d
children b9c65915cc54
files pui-backend.c
line diff
     1.1 --- a/pui-backend.c	Wed Aug 28 13:29:23 2019 +0200
     1.2 +++ b/pui-backend.c	Thu Aug 29 13:48:47 2019 +0200
     1.3 @@ -36,7 +36,8 @@
     1.4  #include "pui-get-updates.h"
     1.5  #include "pui-types.h"
     1.6  
     1.7 -#define	LOW_BATTERY_THRESHOLD	10.0
     1.8 +#define	LOW_BATTERY_THRESHOLD		10.0	/* % */
     1.9 +#define	UPDATES_CHANGED_UNBLOCK_DELAY	4	/* s */
    1.10  
    1.11  struct _PuiBackend {
    1.12  	GObject		parent_instance;
    1.13 @@ -56,7 +57,8 @@
    1.14  	PkNetworkEnum	network_state;
    1.15  	gboolean	inhibited;
    1.16  	gboolean	is_battery_low;
    1.17 -	guint		periodic_check_id;
    1.18 +	guint		check_id;
    1.19 +	guint		unblock_updates_changed_id;
    1.20  	guint		refresh_interval;
    1.21  	gboolean	use_mobile_connection;
    1.22  	guint		important_updates;
    1.23 @@ -90,6 +92,7 @@
    1.24  static GParamSpec *properties[PROP_LAST] = { NULL };
    1.25  
    1.26  static gboolean	periodic_check(gpointer);
    1.27 +static void	on_updates_changed(PkControl *, gpointer);
    1.28  
    1.29  GQuark
    1.30  pui_backend_error_quark(void)
    1.31 @@ -120,6 +123,18 @@
    1.32  	}
    1.33  }
    1.34  
    1.35 +static gboolean
    1.36 +unblock_updates_changed(gpointer user_data)
    1.37 +{
    1.38 +	PuiBackend	*self = user_data;
    1.39 +
    1.40 +	g_signal_handlers_unblock_by_func(self->pk_control, on_updates_changed,
    1.41 +	    self);
    1.42 +	self->unblock_updates_changed_id = 0;
    1.43 +
    1.44 +	return (G_SOURCE_REMOVE);
    1.45 +}
    1.46 +
    1.47  static void
    1.48  on_get_updates_finished(GObject *source_object, GAsyncResult *async_result,
    1.49      gpointer user_data)
    1.50 @@ -172,16 +187,55 @@
    1.51  
    1.52  	/* reschedule periodic check */
    1.53  	if (!self->inhibited) {
    1.54 -		self->periodic_check_id =
    1.55 +		self->check_id =
    1.56  		    g_timeout_add_seconds(PUI_CHECK_UPDATES_INTERVAL,
    1.57  		    periodic_check, self);
    1.58  	}
    1.59  
    1.60 +	/* handle get-updates signals again after a short delay */
    1.61 +	self->unblock_updates_changed_id =
    1.62 +	    g_timeout_add_seconds(UPDATES_CHANGED_UNBLOCK_DELAY,
    1.63 +	    unblock_updates_changed, self);
    1.64 +
    1.65  	if (package_list != NULL) {
    1.66  		g_ptr_array_unref(package_list);
    1.67  	}
    1.68  }
    1.69  
    1.70 +static void
    1.71 +run_check(PuiBackend *self, gboolean refresh_cache)
    1.72 +{
    1.73 +	/* block any get-updates signals emitted when refreshing the cache */
    1.74 +	if (self->unblock_updates_changed_id != 0) {
    1.75 +		/* still blocked */
    1.76 +		g_source_remove(self->unblock_updates_changed_id);
    1.77 +		self->unblock_updates_changed_id = 0;
    1.78 +	} else {
    1.79 +		g_signal_handlers_block_by_func(self->pk_control,
    1.80 +		    G_CALLBACK(on_updates_changed), self);
    1.81 +	}
    1.82 +
    1.83 +	self->cancellable = g_cancellable_new();
    1.84 +	pui_get_updates_async(self->pk_control,
    1.85 +	    refresh_cache ? self->refresh_interval : G_MAXUINT,
    1.86 +	    self->cancellable, on_get_updates_finished, self);
    1.87 +
    1.88 +	/* next periodic check will be scheduled after completion */
    1.89 +	self->check_id = 0;
    1.90 +}
    1.91 +
    1.92 +static gboolean
    1.93 +irregular_check(gpointer user_data)
    1.94 +{
    1.95 +	PuiBackend	*self = user_data;
    1.96 +
    1.97 +	g_debug("running check");
    1.98 +
    1.99 +	run_check(self, FALSE);
   1.100 +
   1.101 +	return (G_SOURCE_REMOVE);
   1.102 +}
   1.103 +
   1.104  static gboolean
   1.105  periodic_check(gpointer user_data)
   1.106  {
   1.107 @@ -189,12 +243,7 @@
   1.108  
   1.109  	g_debug("running periodic check");
   1.110  
   1.111 -	self->cancellable = g_cancellable_new();
   1.112 -	pui_get_updates_async(self->pk_control, self->refresh_interval,
   1.113 -	    self->cancellable, on_get_updates_finished, self);
   1.114 -
   1.115 -	/* next periodic check will be scheduled after completion */
   1.116 -	self->periodic_check_id = 0;
   1.117 +	run_check(self, TRUE);
   1.118  
   1.119  	return (G_SOURCE_REMOVE);
   1.120  }
   1.121 @@ -217,8 +266,8 @@
   1.122  	self->inhibited = inhibited;
   1.123  	if (inhibited) {
   1.124  		/* cancel periodic checks */
   1.125 -		if (self->periodic_check_id != 0) {
   1.126 -			g_source_remove(self->periodic_check_id);
   1.127 +		if (self->check_id != 0) {
   1.128 +			g_source_remove(self->check_id);
   1.129  		}
   1.130  
   1.131  		/* cancel running operation */
   1.132 @@ -239,7 +288,7 @@
   1.133  		remaining_time = (elapsed_time < PUI_CHECK_UPDATES_INTERVAL) ?
   1.134  		    PUI_CHECK_UPDATES_INTERVAL - elapsed_time :
   1.135  		    PUI_STARTUP_DELAY;
   1.136 -		self->periodic_check_id = g_timeout_add_seconds(remaining_time,
   1.137 +		self->check_id = g_timeout_add_seconds(remaining_time,
   1.138  		    periodic_check, self);
   1.139  	}
   1.140  }
   1.141 @@ -301,9 +350,14 @@
   1.142  {
   1.143  	PuiBackend	*self = PUI_BACKEND(object);
   1.144  
   1.145 -	if (self->periodic_check_id != 0) {
   1.146 -		g_source_remove(self->periodic_check_id);
   1.147 -		self->periodic_check_id = 0;
   1.148 +	if (self->check_id != 0) {
   1.149 +		g_source_remove(self->check_id);
   1.150 +		self->check_id = 0;
   1.151 +	}
   1.152 +
   1.153 +	if (self->unblock_updates_changed_id != 0) {
   1.154 +		g_source_remove(self->unblock_updates_changed_id);
   1.155 +		self->unblock_updates_changed_id = 0;
   1.156  	}
   1.157  
   1.158  	if (self->transaction_list != NULL) {
   1.159 @@ -493,19 +547,18 @@
   1.160  {
   1.161  	PuiBackend	*self = user_data;
   1.162  
   1.163 -	g_debug("number of updates changed");
   1.164 +	g_debug("package metatdata cache invalidated");
   1.165  
   1.166  	/*
   1.167  	 * schedule a check after a short delay so that a rapid succession of
   1.168  	 * signals is coalesced
   1.169  	 */
   1.170  	if (!self->inhibited) {
   1.171 -		if (self->periodic_check_id != 0) {
   1.172 -			g_source_remove(self->periodic_check_id);
   1.173 +		if (self->check_id != 0) {
   1.174 +			g_source_remove(self->check_id);
   1.175  		}
   1.176 -		self->periodic_check_id =
   1.177 -		    g_timeout_add_seconds(PUI_STARTUP_DELAY, periodic_check,
   1.178 -		    self);
   1.179 +		self->check_id = g_timeout_add_seconds(PUI_STARTUP_DELAY,
   1.180 +		    irregular_check, self);
   1.181  	}
   1.182  }
   1.183  
   1.184 @@ -639,7 +692,7 @@
   1.185  	/* get notification when the network state changes */
   1.186  	g_signal_connect(self->pk_control, "notify::network-state",
   1.187  	    G_CALLBACK(on_notify_network_state), self);
   1.188 -	/* get notifications when the available package updates change */
   1.189 +	/* get notifications when the package metatdata cache is invalidated */
   1.190  	g_signal_connect(self->pk_control, "updates-changed",
   1.191  	    G_CALLBACK(on_updates_changed), self);
   1.192  	/* get notifications when an application restart is required */