summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGaël Bonithon <gael@xfce.org>2021-12-28 16:20:37 +0100
committerGaël Bonithon <gael@xfce.org>2021-12-29 13:09:43 +0100
commita188f1c30f8e7c98373d620832933522ad29d14f (patch)
tree79c22dab921c185c3fb5b3bef32d291627ea01ae
parentad8d6ac59b20ab8ccbb3ce4d56c71d25f2a435b6 (diff)
downloadtumbler-a188f1c30f8e7c98373d620832933522ad29d14f.tar.gz
Try all available thumbnailers before declaring failure
The request thumbnailer array no longer contains one thumbnailer per URI, but the list of available thumbnailers for this URI (after applying the filters of the configuration file), sorted by priority. For a given URI, we browse the thumbnailer list until we succeed in generating a thumbnail. An error signal is only issued if the last thumbnailer has failed. Intermediate errors are only displayed if debug logging is enabled. Closes #50.
-rw-r--r--tumbler/tumbler-thumbnailer.c31
-rw-r--r--tumbler/tumbler-thumbnailer.h4
-rw-r--r--tumblerd/tumbler-group-scheduler.c48
-rw-r--r--tumblerd/tumbler-lifo-scheduler.c54
-rw-r--r--tumblerd/tumbler-registry.c13
-rw-r--r--tumblerd/tumbler-registry.h2
-rw-r--r--tumblerd/tumbler-scheduler.c36
-rw-r--r--tumblerd/tumbler-scheduler.h12
-rw-r--r--tumblerd/tumbler-service.c4
9 files changed, 134 insertions, 70 deletions
diff --git a/tumbler/tumbler-thumbnailer.c b/tumbler/tumbler-thumbnailer.c
index 27d3177..5074d35 100644
--- a/tumbler/tumbler-thumbnailer.c
+++ b/tumbler/tumbler-thumbnailer.c
@@ -282,20 +282,28 @@ tumbler_thumbnailer_supports_hash_key (TumblerThumbnailer *thumbnailer,
-TumblerThumbnailer **
-tumbler_thumbnailer_array_copy (TumblerThumbnailer **thumbnailers,
- guint length)
+static gpointer
+tumbler_thumbnailer_object_ref (gconstpointer src,
+ gpointer data)
{
- TumblerThumbnailer **copy;
- guint n;
+ return g_object_ref ((gpointer) src);
+}
+
+
+
+GList **
+tumbler_thumbnailer_array_copy (GList **thumbnailers,
+ guint length)
+{
+ GList **copy;
+ guint n;
g_return_val_if_fail (thumbnailers != NULL, NULL);
- copy = g_new0 (TumblerThumbnailer *, length + 1);
+ copy = g_new0 (GList *, length + 1);
for (n = 0; n < length; ++n)
- if (thumbnailers[n] != NULL)
- copy[n] = g_object_ref (thumbnailers[n]);
+ copy[n] = g_list_copy_deep (thumbnailers[n], tumbler_thumbnailer_object_ref, NULL);
copy[n] = NULL;
@@ -305,14 +313,13 @@ tumbler_thumbnailer_array_copy (TumblerThumbnailer **thumbnailers,
void
-tumbler_thumbnailer_array_free (TumblerThumbnailer **thumbnailers,
- guint length)
+tumbler_thumbnailer_array_free (GList **thumbnailers,
+ guint length)
{
guint n;
for (n = 0; thumbnailers != NULL && n < length; ++n)
- if (thumbnailers[n] != NULL)
- g_object_unref (thumbnailers[n]);
+ g_list_free_full (thumbnailers[n], g_object_unref);
g_free (thumbnailers);
}
diff --git a/tumbler/tumbler-thumbnailer.h b/tumbler/tumbler-thumbnailer.h
index b983d4e..0bbd7d2 100644
--- a/tumbler/tumbler-thumbnailer.h
+++ b/tumbler/tumbler-thumbnailer.h
@@ -78,9 +78,9 @@ gboolean tumbler_thumbnailer_supports_location (TumblerThumbnailer
gboolean tumbler_thumbnailer_supports_hash_key (TumblerThumbnailer *thumbnailer,
const gchar *hash_key);
-TumblerThumbnailer **tumbler_thumbnailer_array_copy (TumblerThumbnailer **thumbnailers,
+GList **tumbler_thumbnailer_array_copy (GList **thumbnailers,
guint length);
-void tumbler_thumbnailer_array_free (TumblerThumbnailer **thumbnailers,
+void tumbler_thumbnailer_array_free (GList **thumbnailers,
guint length);
G_END_DECLS
diff --git a/tumblerd/tumbler-group-scheduler.c b/tumblerd/tumbler-group-scheduler.c
index f756f7a..a266542 100644
--- a/tumblerd/tumbler-group-scheduler.c
+++ b/tumblerd/tumbler-group-scheduler.c
@@ -423,7 +423,7 @@ tumbler_group_scheduler_thread (gpointer data,
GList *ready_uris;
GList *cached_uris = NULL;
GList *missing_uris = NULL;
- GList *lp;
+ GList *lp, *lq;
guint n;
gint error_code = 0;
GQuark error_domain = 0;
@@ -550,25 +550,33 @@ tumbler_group_scheduler_thread (gpointer data,
}
tumbler_mutex_unlock (scheduler->mutex);
- /* connect to the error signal of the thumbnailer */
- g_signal_connect (request->thumbnailers[n], "error",
- G_CALLBACK (tumbler_group_scheduler_thumbnailer_error),
- &uri_errors);
-
- /* connect to the ready signal of the thumbnailer */
- g_signal_connect (request->thumbnailers[n], "ready",
- G_CALLBACK (tumbler_group_scheduler_thumbnailer_ready),
- &ready_uris);
-
- /* tell the thumbnailer to generate the thumbnail */
- tumbler_thumbnailer_create (request->thumbnailers[n],
- request->cancellables[n],
- request->infos[n]);
-
- /* disconnect from all signals when we're finished */
- g_signal_handlers_disconnect_matched (request->thumbnailers[n],
- G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, request);
+ for (lq = request->thumbnailers[n]; lq != NULL; lq = lq->next)
+ {
+ /* forward only the error signal of the last thumbnailer */
+ if (lq->next == NULL)
+ g_signal_connect (lq->data, "error",
+ G_CALLBACK (tumbler_group_scheduler_thumbnailer_error), &uri_errors);
+ else if (tumbler_util_is_debug_logging_enabled (G_LOG_DOMAIN))
+ g_signal_connect (lq->data, "error",
+ G_CALLBACK (tumbler_scheduler_thumberr_debuglog), request);
+
+ /* connect to the ready signal of the thumbnailer */
+ g_signal_connect (lq->data, "ready",
+ G_CALLBACK (tumbler_group_scheduler_thumbnailer_ready), &ready_uris);
+
+ /* cancel lower priority thumbnailers for this uri on ready signal */
+ g_signal_connect_swapped (lq->data, "ready", G_CALLBACK (g_cancellable_cancel),
+ request->cancellables[n]);
+
+ /* tell the thumbnailer to generate the thumbnail */
+ tumbler_thumbnailer_create (lq->data, request->cancellables[n], request->infos[n]);
+
+ /* disconnect from all signals when we're finished */
+ g_signal_handlers_disconnect_by_data (lq->data, &uri_errors);
+ g_signal_handlers_disconnect_by_data (lq->data, &ready_uris);
+ g_signal_handlers_disconnect_by_data (lq->data, request);
+ g_signal_handlers_disconnect_by_data (lq->data, request->cancellables[n]);
+ }
}
tumbler_mutex_lock (scheduler->mutex);
diff --git a/tumblerd/tumbler-lifo-scheduler.c b/tumblerd/tumbler-lifo-scheduler.c
index e19d811..f1ff821 100644
--- a/tumblerd/tumbler-lifo-scheduler.c
+++ b/tumblerd/tumbler-lifo-scheduler.c
@@ -362,7 +362,7 @@ tumbler_lifo_scheduler_thread (gpointer data,
GError *error = NULL;
GList *cached_uris = NULL;
GList *missing_uris = NULL;
- GList *lp;
+ GList *lp, *lq;
guint n;
g_return_if_fail (TUMBLER_IS_LIFO_SCHEDULER (scheduler));
@@ -475,29 +475,35 @@ tumbler_lifo_scheduler_thread (gpointer data,
return;
}
- /* We immediately forward error and ready so that clients rapidly know
- * when individual thumbnails are ready. It's a LIFO for better inter-
- * activity with the clients, so we assume this behaviour to be desired. */
-
- /* connect to the error signal of the thumbnailer */
- g_signal_connect (request->thumbnailers[n], "error",
- G_CALLBACK (tumbler_lifo_scheduler_thumbnailer_error),
- request);
-
- /* connect to the ready signal of the thumbnailer */
- g_signal_connect (request->thumbnailers[n], "ready",
- G_CALLBACK (tumbler_lifo_scheduler_thumbnailer_ready),
- request);
-
- /* tell the thumbnailer to generate the thumbnail */
- tumbler_thumbnailer_create (request->thumbnailers[n],
- request->cancellables[n],
- request->infos[n]);
-
- /* disconnect from all signals when we're finished */
- g_signal_handlers_disconnect_matched (request->thumbnailers[n],
- G_SIGNAL_MATCH_DATA,
- 0, 0, NULL, NULL, request);
+ for (lq = request->thumbnailers[n]; lq != NULL; lq = lq->next)
+ {
+ /* We immediately forward error and ready so that clients rapidly know
+ * when individual thumbnails are ready. It's a LIFO for better inter-
+ * activity with the clients, so we assume this behaviour to be desired. */
+
+ /* forward only the error signal of the last thumbnailer */
+ if (lq->next == NULL)
+ g_signal_connect (lq->data, "error",
+ G_CALLBACK (tumbler_lifo_scheduler_thumbnailer_error), request);
+ else if (tumbler_util_is_debug_logging_enabled (G_LOG_DOMAIN))
+ g_signal_connect (lq->data, "error",
+ G_CALLBACK (tumbler_scheduler_thumberr_debuglog), request);
+
+ /* connect to the ready signal of the thumbnailer */
+ g_signal_connect (lq->data, "ready",
+ G_CALLBACK (tumbler_lifo_scheduler_thumbnailer_ready), request);
+
+ /* cancel lower priority thumbnailers for this uri on ready signal */
+ g_signal_connect_swapped (lq->data, "ready", G_CALLBACK (g_cancellable_cancel),
+ request->cancellables[n]);
+
+ /* tell the thumbnailer to generate the thumbnail */
+ tumbler_thumbnailer_create (lq->data, request->cancellables[n], request->infos[n]);
+
+ /* disconnect from all signals when we're finished */
+ g_signal_handlers_disconnect_by_data (lq->data, request);
+ g_signal_handlers_disconnect_by_data (lq->data, request->cancellables[n]);
+ }
}
/* free list */
diff --git a/tumblerd/tumbler-registry.c b/tumblerd/tumbler-registry.c
index 32cdbfc..6f75654 100644
--- a/tumblerd/tumbler-registry.c
+++ b/tumblerd/tumbler-registry.c
@@ -411,12 +411,12 @@ tumbler_registry_get_thumbnailers (TumblerRegistry *registry)
-TumblerThumbnailer **
+GList **
tumbler_registry_get_thumbnailer_array (TumblerRegistry *registry,
TumblerFileInfo **infos,
guint length)
{
- TumblerThumbnailer **thumbnailers = NULL;
+ GList **thumbnailers = NULL;
gchar *hash_key;
gchar *scheme;
guint n;
@@ -432,7 +432,7 @@ tumbler_registry_get_thumbnailer_array (TumblerRegistry *registry,
tumbler_mutex_lock (registry->mutex);
/* allocate the thumbnailer array */
- thumbnailers = g_new0 (TumblerThumbnailer *, length + 1);
+ thumbnailers = g_new0 (GList *, length + 1);
/* iterate over all URIs */
for (n = 0; n < length; ++n)
@@ -475,11 +475,12 @@ tumbler_registry_get_thumbnailer_array (TumblerRegistry *registry,
}
/* found a usable thumbnailer */
- thumbnailers[n] = g_object_ref (lp->data);
-
- break;
+ thumbnailers[n] = g_list_prepend (thumbnailers[n], g_object_ref (lp->data));
}
+ /* restore thumbnailer priority */
+ thumbnailers[n] = g_list_reverse (thumbnailers[n]);
+
/* cleanup */
g_free (hash_key);
g_free (scheme);
diff --git a/tumblerd/tumbler-registry.h b/tumblerd/tumbler-registry.h
index c58a0e0..9714250 100644
--- a/tumblerd/tumbler-registry.h
+++ b/tumblerd/tumbler-registry.h
@@ -45,7 +45,7 @@ void tumbler_registry_add (TumblerRegistry
void tumbler_registry_remove (TumblerRegistry *registry,
TumblerThumbnailer *thumbnailer);
GList *tumbler_registry_get_thumbnailers (TumblerRegistry *registry) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
-TumblerThumbnailer **tumbler_registry_get_thumbnailer_array (TumblerRegistry *registry,
+GList **tumbler_registry_get_thumbnailer_array (TumblerRegistry *registry,
TumblerFileInfo **infos,
guint length) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
void tumbler_registry_update_supported (TumblerRegistry *registry);
diff --git a/tumblerd/tumbler-scheduler.c b/tumblerd/tumbler-scheduler.c
index 2110bc2..8ad820a 100644
--- a/tumblerd/tumbler-scheduler.c
+++ b/tumblerd/tumbler-scheduler.c
@@ -234,7 +234,7 @@ tumbler_scheduler_emit_uri_error (TumblerScheduler *scheduler,
TumblerSchedulerRequest *
tumbler_scheduler_request_new (TumblerFileInfo **infos,
- TumblerThumbnailer **thumbnailers,
+ GList **thumbnailers,
guint length,
const gchar *origin)
{
@@ -335,3 +335,37 @@ tumbler_scheduler_thread_use_lower_priority (void)
sched_setscheduler (0, SCHED_IDLE, &sp);
#endif
}
+
+
+
+void
+tumbler_scheduler_thumberr_debuglog (TumblerThumbnailer *thumbnailer,
+ const gchar *failed_uri,
+ GQuark error_domain,
+ gint error_code,
+ const gchar *message,
+ TumblerSchedulerRequest *request)
+{
+ gchar *text;
+
+ g_return_if_fail (TUMBLER_IS_THUMBNAILER (thumbnailer));
+ g_return_if_fail (failed_uri != NULL);
+ g_return_if_fail (request != NULL);
+ g_return_if_fail (TUMBLER_IS_SCHEDULER (request->scheduler));
+
+ if (error_domain == G_IO_ERROR && error_code == G_IO_ERROR_CANCELLED)
+ return;
+
+ if (error_domain == TUMBLER_ERROR)
+ text = g_strdup (message);
+ else
+ {
+ error_code = TUMBLER_ERROR_OTHER_ERROR_DOMAIN;
+ text = g_strdup_printf ("(domain %s, code %d) %s",
+ g_quark_to_string (error_domain), error_code, message);
+ }
+
+ g_debug ("Failed attempt for job %d, URI '%s': Code %d, message: %s",
+ request->handle, failed_uri, error_code, text);
+ g_free (text);
+}
diff --git a/tumblerd/tumbler-scheduler.h b/tumblerd/tumbler-scheduler.h
index 6423166..a317d66 100644
--- a/tumblerd/tumbler-scheduler.h
+++ b/tumblerd/tumbler-scheduler.h
@@ -81,7 +81,7 @@ void tumbler_scheduler_emit_uri_error (TumblerSchedul
const gchar *uri,
GError *error);
TumblerSchedulerRequest *tumbler_scheduler_request_new (TumblerFileInfo **infos,
- TumblerThumbnailer **thumbnailers,
+ GList **thumbnailers,
guint length,
const gchar *origin);
void tumbler_scheduler_request_free (gpointer data);
@@ -91,9 +91,17 @@ gint tumbler_scheduler_request_compare (gconstpointer
void tumbler_scheduler_thread_use_lower_priority (void);
+/* debug */
+void tumbler_scheduler_thumberr_debuglog (TumblerThumbnailer *thumbnailer,
+ const gchar *failed_uri,
+ GQuark error_domain,
+ gint error_code,
+ const gchar *message,
+ TumblerSchedulerRequest *request);
+
struct _TumblerSchedulerRequest
{
- TumblerThumbnailer **thumbnailers;
+ GList **thumbnailers;
TumblerScheduler *scheduler;
TumblerFileInfo **infos;
GCancellable **cancellables;
diff --git a/tumblerd/tumbler-service.c b/tumblerd/tumbler-service.c
index 8e6fbf1..a60858e 100644
--- a/tumblerd/tumbler-service.c
+++ b/tumblerd/tumbler-service.c
@@ -460,7 +460,7 @@ tumbler_service_scheduler_error (TumblerScheduler *scheduler,
else
{
info->error_code = TUMBLER_ERROR_OTHER_ERROR_DOMAIN;
- info->message = g_strdup_printf ("(%s error, code %d) %s",
+ info->message = g_strdup_printf ("(domain %s, code %d) %s",
g_quark_to_string (error_domain), error_code, message);
}
@@ -716,10 +716,10 @@ tumbler_service_queue_cb (TumblerExportedService *skeleton,
{
TumblerSchedulerRequest *scheduler_request;
TumblerThumbnailFlavor *flavor;
- TumblerThumbnailer **thumbnailers;
TumblerScheduler *scheduler = NULL;
TumblerFileInfo **infos;
TumblerCache *cache;
+ GList **thumbnailers;
GList *iter;
gchar *name;
const gchar *origin;