[Xfce4-commits] <tumbler:master> Rework the TumblerGroupScheduler code. Use a GList for error/ready URIs.
Jannis Pohlmann
noreply at xfce.org
Tue Oct 6 20:54:11 CEST 2009
Updating branch refs/heads/master
to bb8928cb7423a1634f444411d7dbc6e4ea0601ef (commit)
from 437b6b40d0fce61358e1a0ed6ae83b1929a550fe (commit)
commit bb8928cb7423a1634f444411d7dbc6e4ea0601ef
Author: Jannis Pohlmann <jannis at xfce.org>
Date: Tue Oct 6 20:51:29 2009 +0200
Rework the TumblerGroupScheduler code. Use a GList for error/ready URIs.
tumblerd/tumbler-group-scheduler.c | 274 +++++++++++++++++++++++-------------
tumblerd/tumbler-group-scheduler.h | 5 +-
2 files changed, 180 insertions(+), 99 deletions(-)
diff --git a/tumblerd/tumbler-group-scheduler.c b/tumblerd/tumbler-group-scheduler.c
index bbe4654..c128a11 100644
--- a/tumblerd/tumbler-group-scheduler.c
+++ b/tumblerd/tumbler-group-scheduler.c
@@ -1,6 +1,8 @@
/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
- * Copyright (C) 2009, Nokia
+ * Copyright (c) 2009 Jannis Pohlmann <jannis at xfce.org>
+ * Copyright (c) 2009 Nokia,
+ * written by Philip Van Hoof <philip at codeminded.be>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -16,8 +18,6 @@
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
- *
- * Author: Philip Van Hoof <philip at codeminded.be>
*/
#ifdef HAVE_CONFIG_H
@@ -35,6 +35,8 @@
#include <tumblerd/tumbler-group-scheduler.h>
#include <tumblerd/tumbler-scheduler.h>
+
+
/* Property identifiers */
enum
{
@@ -42,6 +44,12 @@ enum
PROP_NAME,
};
+
+
+typedef struct _UriError UriError;
+
+
+
static void tumbler_group_scheduler_iface_init (TumblerSchedulerIface *iface);
static void tumbler_group_scheduler_finalize (GObject *object);
static void tumbler_group_scheduler_get_property (GObject *object,
@@ -56,7 +64,7 @@ static void tumbler_group_scheduler_push (TumblerScheduler
TumblerSchedulerRequest *request);
static void tumbler_group_scheduler_unqueue (TumblerScheduler *scheduler,
guint handle);
-static void tumbler_group_scheduler_finish_request (TumblerGroupScheduler *scheduler,
+static void tumbler_group_scheduler_finish_request (TumblerGroupScheduler *scheduler,
TumblerSchedulerRequest *request);
static void tumbler_group_scheduler_unqueue_request (TumblerSchedulerRequest *request,
gpointer user_data);
@@ -66,10 +74,10 @@ static void tumbler_group_scheduler_thumbnailer_error (TumblerThumbnailer
const gchar *failed_uri,
gint error_code,
const gchar *message,
- GPtrArray *errors);
+ GList **uri_errors);
static void tumbler_group_scheduler_thumbnailer_ready (TumblerThumbnailer *thumbnailer,
const gchar *uri,
- GPtrArray *readies);
+ GList **ready_uris);
@@ -86,9 +94,18 @@ struct _TumblerGroupScheduler
GMutex *mutex;
GList *requests;
guint group;
+
gchar *name;
};
+struct _UriError
+{
+ guint error_code;
+ gchar *message;
+ gchar *failed_uri;
+};
+
+
G_LOCK_DEFINE (group_access_lock);
@@ -133,8 +150,8 @@ tumbler_group_scheduler_init (TumblerGroupScheduler *scheduler)
scheduler->mutex = g_mutex_new ();
scheduler->requests = NULL;
- /* allocate a pool with max. 1 threads for requests */
- scheduler->pool = g_thread_pool_new (tumbler_group_scheduler_thread,
+ /* allocate a pool with one thread for all requests */
+ scheduler->pool = g_thread_pool_new (tumbler_group_scheduler_thread,
scheduler, 1, TRUE, NULL);
}
@@ -155,6 +172,7 @@ tumbler_group_scheduler_finalize (GObject *object)
/* destroy the request list */
g_list_free (scheduler->requests);
+ /* free the scheduler name */
g_free (scheduler->name);
/* destroy the mutex */
@@ -223,8 +241,7 @@ tumbler_group_scheduler_push (TumblerScheduler *scheduler,
tumbler_scheduler_take_request (scheduler, request);
/* prepend the request to the request list */
- group_scheduler->requests =
- g_list_prepend (group_scheduler->requests, request);
+ group_scheduler->requests = g_list_prepend (group_scheduler->requests, request);
/* enqueue the request in the pool */
g_thread_pool_push (group_scheduler->pool, request, NULL);
@@ -246,6 +263,7 @@ tumbler_group_scheduler_unqueue (TumblerScheduler *scheduler,
g_mutex_lock (group_scheduler->mutex);
+ /* unqueue all requests (usually only one) with this handle */
g_list_foreach (group_scheduler->requests,
(GFunc) tumbler_group_scheduler_unqueue_request,
GUINT_TO_POINTER (handle));
@@ -262,11 +280,13 @@ tumbler_group_scheduler_finish_request (TumblerGroupScheduler *scheduler,
g_return_if_fail (TUMBLER_IS_GROUP_SCHEDULER (scheduler));
g_return_if_fail (request != NULL);
+ /* emit a finished signal */
g_signal_emit_by_name (scheduler, "finished", request->handle);
- scheduler->requests = g_list_remove (scheduler->requests,
- request);
+ /* remove the request from the request list */
+ scheduler->requests = g_list_remove (scheduler->requests, request);
+ /* destroy the request */
tumbler_scheduler_request_free (request);
}
@@ -281,43 +301,61 @@ tumbler_group_scheduler_unqueue_request (TumblerSchedulerRequest *request,
g_return_if_fail (request != NULL);
g_return_if_fail (handle != 0);
+ /* mark the request as unqueued if the handles match */
if (request->handle == handle)
request->unqueued = TRUE;
}
-typedef struct {
- guint error_code;
- gchar *message, *failed_uri;
-} GroupError;
+
+
+static UriError *
+uri_error_new (void)
+{
+ UriError *error;
+
+ error = g_slice_new0 (UriError);
+ return error;
+}
+
+
static void
-group_error_free (gpointer data, gpointer user_data)
+uri_error_free (UriError *error)
{
- GroupError *grp_error = data;
+ g_free (error->message);
+ g_free (error->failed_uri);
- g_free (grp_error->message);
- g_free (grp_error->failed_uri);
- g_free (grp_error);
+ g_slice_free (UriError, error);
}
+
+
static void
tumbler_group_scheduler_thread (gpointer data,
gpointer user_data)
{
- TumblerGroupScheduler *scheduler = user_data;
- TumblerSchedulerRequest *request = data;
- TumblerFileInfo *info;
- const gchar **uris;
- gboolean outdated;
- gboolean uri_needs_update;
- guint64 mtime;
- GError *error = NULL;
- GList *cached_uris = NULL;
- GList *missing_uris = NULL;
- GList *thumbnails;
- GList *lp;
- gint n;
- GPtrArray *errors, *readies;
+ TumblerSchedulerRequest *request = data;
+ TumblerGroupScheduler *scheduler = user_data;
+ TumblerFileInfo *info;
+ const gchar **uris;
+ const gchar **failed_uris;
+ const gchar **success_uris;
+ UriError *uri_error;
+ gboolean outdated;
+ gboolean uri_needs_update;
+ GString *message;
+ guint64 mtime;
+ GError *error = NULL;
+ GList *iter;
+ GList *uri_errors;
+ GList *ready_uris;
+ GList *cached_uris = NULL;
+ GList *missing_uris = NULL;
+ GList *thumbnails;
+ GList *lp;
+ guint n;
+ guint i;
+ gint error_code;
g_return_if_fail (TUMBLER_IS_GROUP_SCHEDULER (scheduler));
g_return_if_fail (request != NULL);
@@ -325,7 +363,6 @@ tumbler_group_scheduler_thread (gpointer data,
/* notify others that we're starting to process this request */
g_signal_emit_by_name (request->scheduler, "started", request->handle);
-
/* finish the request if it was unqueued */
if (request->unqueued)
{
@@ -347,47 +384,59 @@ tumbler_group_scheduler_thread (gpointer data,
return;
}
+ /* create a file infor for the current URI */
info = tumbler_file_info_new (request->uris[n]);
uri_needs_update = FALSE;
G_LOCK (group_access_lock);
+ /* try to load thumbnail information about the URI */
if (tumbler_file_info_load (info, NULL, &error))
{
+ /* check if we have a thumbnailer for the URI */
if (request->thumbnailers[n] != NULL)
{
+ /* compute the last modification time of the URI */
mtime = tumbler_file_info_get_mtime (info);
+ /* get a list of all thumbnails for this URI */
thumbnails = tumbler_file_info_get_thumbnails (info);
- for (lp = thumbnails;
- error == NULL && lp != NULL;
- lp = lp->next)
+ /* iterate over them */
+ for (lp = thumbnails; error == NULL && lp != NULL; lp = lp->next)
{
+ /* try to load the thumbnail information */
if (tumbler_thumbnail_load (lp->data, NULL, &error))
{
+ /* check if the thumbnail needs an update */
outdated = tumbler_thumbnail_needs_update (lp->data,
request->uris[n],
mtime);
+ /* if at least one thumbnail is out of date, we need to
+ * regenerate thumbnails for the URI */
uri_needs_update = uri_needs_update || outdated;
}
}
}
else
{
+ /* no thumbnailer for this URI, we need to emit an error */
g_set_error (&error, TUMBLER_ERROR, TUMBLER_ERROR_NO_THUMBNAILER,
_("No thumbnailer available for \"%s\""),
request->uris[n]);
}
}
+ /* release the file info */
g_object_unref (info);
G_UNLOCK (group_access_lock);
+ /* check if the URI is supported */
if (error == NULL)
{
+ /* put it in the right list depending on its thumbnail status */
if (uri_needs_update)
missing_uris = g_list_prepend (missing_uris, GINT_TO_POINTER (n));
else
@@ -395,9 +444,9 @@ tumbler_group_scheduler_thread (gpointer data,
}
else
{
+ /* emit an error for the URI */
tumbler_scheduler_emit_uri_error (TUMBLER_SCHEDULER (scheduler), request,
request->uris[n], error);
-
g_clear_error (&error);
}
}
@@ -405,6 +454,7 @@ tumbler_group_scheduler_thread (gpointer data,
/* check if we have any cached files */
if (cached_uris != NULL)
{
+ /* allocate a URI array and fill it with all cached URIs */
uris = g_new0 (const gchar *, g_list_length (cached_uris) + 1);
for (n = 0, lp = g_list_last (cached_uris); lp != NULL; lp = lp->prev, ++n)
uris[n] = lp->data;
@@ -418,8 +468,10 @@ tumbler_group_scheduler_thread (gpointer data,
g_free (uris);
}
- errors = g_ptr_array_new ();
- readies = g_ptr_array_new ();
+ /* initialize lists for grouping failed URIs and URIs for which
+ * thumbnails are ready */
+ uri_errors = NULL;
+ ready_uris = NULL;
/* iterate over invalid/missing URI list */
for (lp = g_list_last (missing_uris); lp != NULL; lp = lp->prev)
@@ -438,12 +490,12 @@ tumbler_group_scheduler_thread (gpointer data,
/* connect to the error signal of the thumbnailer */
g_signal_connect (request->thumbnailers[n], "error",
G_CALLBACK (tumbler_group_scheduler_thumbnailer_error),
- errors);
+ &uri_errors);
/* connect to the ready signal of the thumbnailer */
g_signal_connect (request->thumbnailers[n], "ready",
G_CALLBACK (tumbler_group_scheduler_thumbnailer_ready),
- readies);
+ &ready_uris);
/* tell the thumbnailer to generate the thumbnail */
tumbler_thumbnailer_create (request->thumbnailers[n], request->uris[n],
@@ -457,53 +509,81 @@ tumbler_group_scheduler_thread (gpointer data,
g_mutex_lock (scheduler->mutex);
- /* We put all the errors and readies together, to avoid DBus traffic */
+ /* We emit all the errors and ready signals together in order to
+ * reduce the overall D-Bus traffic */
- if (errors->len > 0) {
- guint i, error_code;
- GString *message = g_string_new ("");
- GStrv failed_uris = (GStrv) g_malloc0 (sizeof (gchar *) * errors->len);
+ /* check if we have any failed URIs */
+ if (uri_errors != NULL)
+ {
+ /* allocate the failed URIs array */
+ failed_uris = g_new0 (const gchar *, g_list_length (uri_errors) + 1);
- for (i = 0; i < errors->len; i++) {
- GroupError *grp_error = g_ptr_array_index (errors, i);
+ /* allocate the grouped error message */
+ message = g_string_new ("");
- if (i != 0) {
- if (grp_error->message)
- g_string_append_c (message, ' ');
- } else
- error_code = grp_error->error_code;
+ for (iter = uri_errors, n = 0; iter != NULL; iter = iter->next, ++n)
+ {
+ uri_error = iter->data;
- if (grp_error->message)
- g_string_append (message, grp_error->message);
+ /* we use the error code of the first failed URI */
+ if (iter == uri_errors)
+ error_code = uri_error->error_code;
- failed_uris[i] = g_ptr_array_index (errors, i);
- }
+ if (uri_error->message != NULL)
+ {
+ /* we concatenate error messages with a newline inbetween */
+ if (iter != uri_errors && iter->next != NULL)
+ g_string_append_c (message, '\n');
- /* forward the error signal */
- g_signal_emit_by_name (request->scheduler, "error", request->handle,
- failed_uris, error_code, message->str);
+ /* append the current error message */
+ g_string_append (message, uri_error->message);
+ }
- g_free (failed_uris);
- g_string_free (message, TRUE);
- }
+ /* fill the failed_uris array with URIs */
+ failed_uris[n] = uri_error->failed_uri;
+ }
- g_ptr_array_foreach (errors, group_error_free, NULL);
- g_ptr_array_free (errors, TRUE);
+ /* NULL-terminate the failed URI array */
+ failed_uris[n] = NULL;
- if (readies->len > 0) {
- GStrv ready_uris = (GStrv) g_new0 (gchar*, readies->len);
- guint i;
+ /* forward the error signal */
+ g_signal_emit_by_name (request->scheduler, "error", request->handle,
+ failed_uris, error_code, message->str);
- for (i = 0; i < readies->len; i++)
- ready_uris[i] = g_ptr_array_index (readies, i);
+ /* free the failed URIs array. Its contents are owned by the URI errors */
+ g_free (failed_uris);
- g_signal_emit_by_name (request->scheduler, "ready", ready_uris);
+ /* free the error message */
+ g_string_free (message, TRUE);
+ }
+
+ /* free all URI errors and the error URI list */
+ g_list_foreach (uri_errors, (GFunc) uri_error_free, NULL);
+ g_list_free (uri_errors);
+
+ /* check if we have any successfully processed URIs */
+ if (ready_uris != NULL)
+ {
+ /* allocate a string array for successful URIs */
+ success_uris = g_new0 (const gchar *, g_list_length (ready_uris) + 1);
+
+ /* fill the array with all ready URIs */
+ for (iter = ready_uris, n = 0; iter != NULL; iter = iter->next, ++n)
+ success_uris[n] = iter->data;
- g_free (ready_uris);
- }
+ /* NULL-terminate the successful URI array */
+ success_uris[n] = NULL;
- g_ptr_array_foreach (readies, (GFunc) g_free, NULL);
- g_ptr_array_free (readies, TRUE);
+ /* emit a grouped ready signal */
+ g_signal_emit_by_name (request->scheduler, "ready", success_uris);
+
+ /* free the success URI array. Its contents are owned by the ready URI list */
+ g_free (success_uris);
+ }
+
+ /* free the ready URIs */
+ g_list_foreach (ready_uris, (GFunc) g_free, NULL);
+ g_list_free (ready_uris);
/* notify others that we're finished processing the request */
tumbler_group_scheduler_finish_request (scheduler, request);
@@ -514,39 +594,41 @@ tumbler_group_scheduler_thread (gpointer data,
static void
-tumbler_group_scheduler_thumbnailer_error (TumblerThumbnailer *thumbnailer,
- const gchar *failed_uri,
- gint error_code,
- const gchar *message,
- GPtrArray *errors)
+tumbler_group_scheduler_thumbnailer_error (TumblerThumbnailer *thumbnailer,
+ const gchar *failed_uri,
+ gint error_code,
+ const gchar *message,
+ GList **uri_errors)
{
- GroupError *grp_error;
+ UriError *error;
g_return_if_fail (TUMBLER_IS_THUMBNAILER (thumbnailer));
g_return_if_fail (failed_uri != NULL);
+ g_return_if_fail (error_code < 0);
+ g_return_if_fail (uri_errors != NULL);
- grp_error = g_new0 (GroupError, 1);
-
- grp_error->error_code = error_code;
- if (message) {
- grp_error->message = g_strdup (message);
- }
- grp_error->failed_uri = g_strdup (failed_uri);
+ /* allocate a new URI error */
+ error = g_slice_new0 (UriError);
+ error->error_code = error_code;
+ error->message = g_strdup (message);
+ error->failed_uri = g_strdup (failed_uri);
- g_ptr_array_add (errors, grp_error);
+ /* add the error to the list */
+ *uri_errors = g_list_prepend (*uri_errors, error);
}
static void
-tumbler_group_scheduler_thumbnailer_ready (TumblerThumbnailer *thumbnailer,
- const gchar *uri,
- GPtrArray *readies)
+tumbler_group_scheduler_thumbnailer_ready (TumblerThumbnailer *thumbnailer,
+ const gchar *uri,
+ GList **ready_uris)
{
g_return_if_fail (TUMBLER_IS_THUMBNAILER (thumbnailer));
g_return_if_fail (uri != NULL);
+ g_return_if_fail (ready_uris != NULL);
- g_ptr_array_add (readies, g_strdup (uri));
+ *ready_uris = g_list_prepend (*ready_uris, g_strdup (uri));
}
diff --git a/tumblerd/tumbler-group-scheduler.h b/tumblerd/tumbler-group-scheduler.h
index 741adec..dd36bda 100644
--- a/tumblerd/tumbler-group-scheduler.h
+++ b/tumblerd/tumbler-group-scheduler.h
@@ -1,6 +1,7 @@
/* vi:set et ai sw=2 sts=2 ts=2: */
/*-
- * Copyright (C) 2009, Nokia
+ * Copyright (C) 2009 Nokia,
+ * written by Philip Van Hoof <philip at codeminded.be>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -16,8 +17,6 @@
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
- *
- * Author: Philip Van Hoof <philip at codeminded.be>
*/
#ifndef __TUMBLER_GROUP_SCHEDULER_H__
More information about the Xfce4-commits
mailing list