[tracker] tracker_decorator_next(): Queue tasks when a query is needed
- From: Xavier Claessens <xclaesse src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker] tracker_decorator_next(): Queue tasks when a query is needed
- Date: Thu, 6 Feb 2014 18:01:35 +0000 (UTC)
commit 94d4a8512cd330edd60a75f4b9bc839c277e7d08
Author: Xavier Claessens <xavier claessens collabora co uk>
Date: Thu Jan 30 14:08:00 2014 -0500
tracker_decorator_next(): Queue tasks when a query is needed
This avoid double query when calling tracker_decorator_next()
multiple times consecutively.
https://bugzilla.gnome.org/show_bug.cgi?id=719802
src/libtracker-miner/tracker-decorator.c | 220 ++++++++++-------------------
1 files changed, 76 insertions(+), 144 deletions(-)
---
diff --git a/src/libtracker-miner/tracker-decorator.c b/src/libtracker-miner/tracker-decorator.c
index 1e6d364..b0c6934 100644
--- a/src/libtracker-miner/tracker-decorator.c
+++ b/src/libtracker-miner/tracker-decorator.c
@@ -42,7 +42,6 @@
**/
typedef struct _TrackerDecoratorPrivate TrackerDecoratorPrivate;
-typedef struct _TaskData TaskData;
typedef struct _ElemNode ElemNode;
struct _TrackerDecoratorInfo {
@@ -53,12 +52,6 @@ struct _TrackerDecoratorInfo {
gint ref_count;
};
-struct _TaskData {
- TrackerDecorator *decorator;
- GList *first;
- GList *last;
-};
-
struct _ElemNode {
TrackerDecoratorInfo *info;
gint id;
@@ -73,6 +66,7 @@ struct _TrackerDecoratorPrivate {
GHashTable *elems;
GPtrArray *sparql_buffer;
GTimer *timer;
+ GQueue next_elem_queue;
GArray *class_name_ids;
gint rdf_type_id;
@@ -105,8 +99,6 @@ static GInitableIface *parent_initable_iface;
static GQuark tracker_decorator_error_quark (void);
static void tracker_decorator_initable_iface_init (GInitableIface *iface);
-static void query_next_items (TrackerDecorator *decorator,
- GTask *task);
G_DEFINE_QUARK (TrackerDecoratorError, tracker_decorator_error)
@@ -148,31 +140,6 @@ tracker_decorator_info_unref (TrackerDecoratorInfo *info)
g_slice_free (TrackerDecoratorInfo, info);
}
-static TaskData *
-task_data_new (TrackerDecorator *decorator,
- GList *first,
- GList *last)
-{
- TaskData *data;
-
- data = g_slice_new0 (TaskData);
- data->decorator = decorator;
- data->first = first;
- data->last = last;
-
- return data;
-}
-
-static void
-task_data_free (TaskData *data)
-{
- if (!data) {
- return;
- }
-
- g_slice_free (TaskData, data);
-}
-
static void
decorator_update_state (TrackerDecorator *decorator,
const gchar *message,
@@ -1035,92 +1002,32 @@ tracker_decorator_delete_id (TrackerDecorator *decorator,
element_remove_by_id (decorator, id);
}
-static GList *
-find_first_free_node (TrackerDecorator *decorator)
-{
- TrackerDecoratorPrivate *priv;
- GList *l;
-
- priv = decorator->priv;
-
- if (!priv->elem_queue->head)
- return NULL;
-
- for (l = priv->elem_queue->head; l; l = l->next) {
- ElemNode *node = l->data;
-
- if (!node->info || !node->info->task)
- return l;
- }
-
- return NULL;
-}
-
-static void
-complete_task (GTask *task,
- ElemNode *node)
-{
- g_assert (node->info);
-
- element_ensure_task (node, g_task_get_source_object (task));
- g_task_return_pointer (task, node->info,
- (GDestroyNotify) tracker_decorator_info_unref);
- g_object_unref (task);
-}
-
-static void
-check_task_complete (TrackerDecorator *decorator,
- GTask *task)
-{
- GList *first, *last;
- TaskData *data;
-
- data = g_task_get_task_data (task);
- first = data->first;
- last = data->last->next;
-
- while (first != last) {
- ElemNode *node;
- GList *next;
-
- node = first->data;
- next = first->next;
-
- if (node->info) {
- complete_task (task, node);
- return;
- }
-
- element_remove_link (decorator, first, TRUE);
- first = next;
- }
-
- /* If this is reached, no queried IDs
- * got data in the query, so try again.
- */
- query_next_items (decorator, task);
-}
+static void complete_tasks_or_query (TrackerDecorator *decorator);
static void
query_next_items_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
+ TrackerDecorator *decorator = user_data;
TrackerDecoratorPrivate *priv;
TrackerSparqlConnection *conn;
TrackerSparqlCursor *cursor;
- GTask *task = user_data;
GError *error = NULL;
- TaskData *data;
conn = TRACKER_SPARQL_CONNECTION (object);
cursor = tracker_sparql_connection_query_finish (conn, result, &error);
- data = g_task_get_task_data (task);
- priv = data->decorator->priv;
+ priv = decorator->priv;
if (error) {
- g_task_return_error (task, error);
- g_object_unref (task);
+ GTask *task;
+
+ while ((task = g_queue_pop_head (&priv->next_elem_queue))) {
+ g_task_return_error (task, g_error_copy (error));
+ g_object_unref (task);
+ }
+
+ g_clear_error (&error);
return;
}
@@ -1137,51 +1044,37 @@ query_next_items_cb (GObject *object,
g_object_unref (cursor);
- check_task_complete (data->decorator, task);
+ complete_tasks_or_query (decorator);
}
static void
query_next_items (TrackerDecorator *decorator,
- GTask *task)
+ GList *l)
{
TrackerSparqlConnection *sparql_conn;
TrackerDecoratorPrivate *priv;
- GList *items, *last;
GString *id_string;
- TaskData *data;
gchar *query;
- gint i;
+ guint count = 0;
priv = decorator->priv;
- items = find_first_free_node (decorator);
-
- if (!items) {
- GError *error;
-
- error = g_error_new (tracker_decorator_error_quark (),
- TRACKER_DECORATOR_ERROR_EMPTY,
- "There are no items left");
- g_task_return_error (task, error);
- g_object_unref (task);
- return;
- }
- sparql_conn = tracker_miner_get_connection (TRACKER_MINER (decorator));
id_string = g_string_new (NULL);
+ for (; l != NULL && count < QUERY_BATCH_SIZE; l = l->next) {
+ ElemNode *node = l->data;
- for (i = 0; i < QUERY_BATCH_SIZE && items; i++) {
- ElemNode *node;
-
- last = items;
- node = items->data;
- items = items->next;
+ if (node->info)
+ continue;
if (id_string->len > 0)
g_string_append_c (id_string, ',');
g_string_append_printf (id_string, "%d", node->id);
+ count++;
}
+ g_assert (count > 0);
+
query = g_strdup_printf ("SELECT ?urn"
" tracker:id(?urn) "
" nie:url(?urn) "
@@ -1191,15 +1084,56 @@ query_next_items (TrackerDecorator *decorator,
" ! EXISTS { ?urn nie:dataSource <%s> })"
"}", id_string->str, priv->data_source);
- data = task_data_new (decorator, priv->elem_queue->head, last);
- g_task_set_task_data (task, data, (GDestroyNotify) task_data_free);
+ sparql_conn = tracker_miner_get_connection (TRACKER_MINER (decorator));
tracker_sparql_connection_query_async (sparql_conn, query,
- g_task_get_cancellable (task),
- query_next_items_cb, task);
+ NULL,
+ query_next_items_cb, decorator);
g_string_free (id_string, TRUE);
g_free (query);
}
+static void
+complete_tasks_or_query (TrackerDecorator *decorator)
+{
+ TrackerDecoratorPrivate *priv;
+ GList *l;
+ GTask *task;
+
+ priv = decorator->priv;
+
+ for (l = priv->elem_queue->head; l != NULL; l = l->next) {
+ ElemNode *node = l->data;
+
+ /* The next item isn't queried yet, do it now */
+ if (!node->info) {
+ query_next_items (decorator, l);
+ return;
+ }
+
+ /* If the item is not already being processed, we can complete a
+ * task with it. */
+ if (!node->info->task) {
+ task = g_queue_pop_head (&priv->next_elem_queue);
+ element_ensure_task (node, decorator);
+ g_task_return_pointer (task, node->info,
+ (GDestroyNotify) tracker_decorator_info_unref);
+ g_object_unref (task);
+
+ if (g_queue_is_empty (&priv->next_elem_queue))
+ return;
+ }
+ }
+
+ /* There is no element left, or they are all being processed already */
+ while ((task = g_queue_pop_head (&priv->next_elem_queue))) {
+ g_task_return_new_error (task,
+ tracker_decorator_error_quark (),
+ TRACKER_DECORATOR_ERROR_EMPTY,
+ "There are no items left");
+ g_object_unref (task);
+ }
+}
+
/**
* tracker_decorator_next:
* @decorator: a #TrackerDecorator.
@@ -1222,12 +1156,13 @@ tracker_decorator_next (TrackerDecorator *decorator,
GAsyncReadyCallback callback,
gpointer user_data)
{
- ElemNode *node = NULL;
+ TrackerDecoratorPrivate *priv;
GTask *task;
- GList *elem;
g_return_if_fail (TRACKER_IS_DECORATOR (decorator));
+ priv = decorator->priv;
+
task = g_task_new (decorator, cancellable, callback, user_data);
if (tracker_miner_is_paused (TRACKER_MINER (decorator))) {
@@ -1241,15 +1176,12 @@ tracker_decorator_next (TrackerDecorator *decorator,
return;
}
- elem = find_first_free_node (decorator);
-
- if (elem)
- node = elem->data;
-
- if (node && node->info)
- complete_task (task, node);
- else
- query_next_items (decorator, task);
+ /* Push the task in a queue, for the case this function is called
+ * multiple before it finishes. */
+ g_queue_push_tail (&priv->next_elem_queue, task);
+ if (g_queue_get_length (&priv->next_elem_queue) == 1) {
+ complete_tasks_or_query (decorator);
+ }
}
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]