fetcher: Track outstanding requests with a table
Track outstanding HTTP requests in a table for easier debugging. Also fixes a bug discussed in https://bugzilla.gnome.org/755224 where the outstanding request counter was not decremented in the event of an error, which could result in the fetcher hitting its max request limit and locking up. The bug is fixed by removing the request struct from the table in pending_uri_free(), which is always called regardless of error, so the outstanding request count is always accurate.
This commit is contained in:
parent
771075d319
commit
e21188a245
|
|
@ -58,30 +58,6 @@ typedef struct {
|
|||
GTask *task;
|
||||
} OstreeFetcherPendingURI;
|
||||
|
||||
static int
|
||||
pending_task_compare (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer unused)
|
||||
{
|
||||
gint priority_a = g_task_get_priority (G_TASK (a));
|
||||
gint priority_b = g_task_get_priority (G_TASK (b));
|
||||
|
||||
return (priority_a == priority_b) ? 0 :
|
||||
(priority_a < priority_b) ? -1 : 1;
|
||||
}
|
||||
|
||||
static void
|
||||
pending_uri_free (OstreeFetcherPendingURI *pending)
|
||||
{
|
||||
soup_uri_free (pending->uri);
|
||||
g_clear_object (&pending->self);
|
||||
g_clear_object (&pending->request);
|
||||
g_clear_object (&pending->request_body);
|
||||
g_free (pending->out_tmpfile);
|
||||
g_clear_object (&pending->out_stream);
|
||||
g_free (pending);
|
||||
}
|
||||
|
||||
struct OstreeFetcher
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
|
@ -101,13 +77,39 @@ struct OstreeFetcher
|
|||
guint total_requests;
|
||||
|
||||
/* Queue for libsoup, see bgo#708591 */
|
||||
gint outstanding;
|
||||
GQueue pending_queue;
|
||||
GHashTable *outstanding;
|
||||
gint max_outstanding;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (OstreeFetcher, _ostree_fetcher, G_TYPE_OBJECT)
|
||||
|
||||
static int
|
||||
pending_task_compare (gconstpointer a,
|
||||
gconstpointer b,
|
||||
gpointer unused)
|
||||
{
|
||||
gint priority_a = g_task_get_priority (G_TASK (a));
|
||||
gint priority_b = g_task_get_priority (G_TASK (b));
|
||||
|
||||
return (priority_a == priority_b) ? 0 :
|
||||
(priority_a < priority_b) ? -1 : 1;
|
||||
}
|
||||
|
||||
static void
|
||||
pending_uri_free (OstreeFetcherPendingURI *pending)
|
||||
{
|
||||
g_hash_table_remove (pending->self->outstanding, pending);
|
||||
|
||||
soup_uri_free (pending->uri);
|
||||
g_clear_object (&pending->self);
|
||||
g_clear_object (&pending->request);
|
||||
g_clear_object (&pending->request_body);
|
||||
g_free (pending->out_tmpfile);
|
||||
g_clear_object (&pending->out_stream);
|
||||
g_free (pending);
|
||||
}
|
||||
|
||||
static void
|
||||
_ostree_fetcher_finalize (GObject *object)
|
||||
{
|
||||
|
|
@ -124,6 +126,8 @@ _ostree_fetcher_finalize (GObject *object)
|
|||
while (!g_queue_is_empty (&self->pending_queue))
|
||||
g_object_unref (g_queue_pop_head (&self->pending_queue));
|
||||
|
||||
g_hash_table_destroy (self->outstanding);
|
||||
|
||||
G_OBJECT_CLASS (_ostree_fetcher_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
|
@ -199,6 +203,8 @@ _ostree_fetcher_init (OstreeFetcher *self)
|
|||
self->sending_messages = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify)g_object_unref);
|
||||
self->output_stream_set = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_object_unref);
|
||||
|
||||
self->outstanding = g_hash_table_new_full (NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
OstreeFetcher *
|
||||
|
|
@ -272,7 +278,7 @@ ostree_fetcher_process_pending_queue (OstreeFetcher *self)
|
|||
{
|
||||
|
||||
while (g_queue_peek_head (&self->pending_queue) != NULL &&
|
||||
self->outstanding < self->max_outstanding)
|
||||
g_hash_table_size (self->outstanding) < self->max_outstanding)
|
||||
{
|
||||
GTask *task;
|
||||
OstreeFetcherPendingURI *pending;
|
||||
|
|
@ -283,7 +289,9 @@ ostree_fetcher_process_pending_queue (OstreeFetcher *self)
|
|||
pending = g_task_get_task_data (task);
|
||||
cancellable = g_task_get_cancellable (task);
|
||||
|
||||
self->outstanding++;
|
||||
/* pending_uri_free() removes this. */
|
||||
g_hash_table_add (self->outstanding, pending);
|
||||
|
||||
soup_request_send_async (pending->request,
|
||||
cancellable,
|
||||
on_request_sent,
|
||||
|
|
@ -321,7 +329,6 @@ finish_stream (OstreeFetcherPendingURI *pending,
|
|||
/* Now that we've finished downloading, continue with other queued
|
||||
* requests.
|
||||
*/
|
||||
pending->self->outstanding--;
|
||||
ostree_fetcher_process_pending_queue (pending->self);
|
||||
|
||||
if (stbuf.st_size < pending->content_length)
|
||||
|
|
|
|||
Loading…
Reference in New Issue