[tracker/clientapi-2: 2/20] Adapted the Evolution plugin to new TrackerClient API



commit 08284c313a54a571ded95a30b5f02cd174cb8d3e
Author: Philip Van Hoof <philip codeminded be>
Date:   Tue Jan 12 15:01:23 2010 +0100

    Adapted the Evolution plugin to new TrackerClient API

 src/libtracker-client/tracker.c                  |   42 +++++-
 src/libtracker-client/tracker.h                  |    2 +
 src/plugins/evolution/tracker-evolution-plugin.c |  162 ++++++++++++++--------
 3 files changed, 142 insertions(+), 64 deletions(-)
---
diff --git a/src/libtracker-client/tracker.c b/src/libtracker-client/tracker.c
index 2f39b34..8607090 100644
--- a/src/libtracker-client/tracker.c
+++ b/src/libtracker-client/tracker.c
@@ -121,6 +121,7 @@ enum {
 	PROP_0 = 0,
 	PROP_TIMEOUT,
 	PROP_ENABLE_WARNINGS,
+	PROP_FORCE_SERVICE,
 };
 
 static guint pending_call_id = 0;
@@ -139,6 +140,7 @@ static gboolean start_service               (DBusConnection *connection,
 typedef struct {
 	gint timeout;
 	gboolean enable_warnings;
+	gboolean force_service;
 } TrackerClientPrivate;
 
 G_DEFINE_TYPE(TrackerClient, tracker_client, G_TYPE_OBJECT)
@@ -198,6 +200,14 @@ tracker_client_class_init (TrackerClientClass *klass)
 	                                                       TRUE,
 	                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
+	g_object_class_install_property (object_class,
+	                                 PROP_FORCE_SERVICE,
+	                                 g_param_spec_boolean ("force-service",
+	                                                       "Force service startup",
+	                                                       "Force service startup",
+	                                                       TRUE,
+	                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
 	g_type_class_add_private (object_class, sizeof (TrackerClientPrivate));
 }
 
@@ -213,7 +223,10 @@ tracker_client_set_property (GObject      *object,
 
 	switch (prop_id) {
 	case PROP_ENABLE_WARNINGS:
-			priv->enable_warnings = g_value_get_boolean (value);
+		priv->enable_warnings = g_value_get_boolean (value);
+		break;
+	case PROP_FORCE_SERVICE:
+		priv->force_service = g_value_get_boolean (value);
 		break;
 	case PROP_TIMEOUT:
 		val = g_value_get_int (value);
@@ -239,6 +252,9 @@ tracker_client_get_property (GObject      *object,
 	case PROP_ENABLE_WARNINGS:
 		g_value_set_boolean (value, priv->enable_warnings);
 		break;
+	case PROP_FORCE_SERVICE:
+		g_value_set_boolean (value, priv->force_service);
+		break;
 	case PROP_TIMEOUT:
 		g_value_set_int (value, priv->timeout);
 		break;
@@ -263,7 +279,7 @@ tracker_client_init (TrackerClient *client)
 		return;
 	}
 
-	if (!start_service (dbus_g_connection_get_connection (connection), TRACKER_SERVICE)) {
+	if (priv->force_service && !start_service (dbus_g_connection_get_connection (connection), TRACKER_SERVICE)) {
 		/* unable to start tracker-store */
 		dbus_g_connection_unref (connection);
 		return;
@@ -470,8 +486,26 @@ tracker_connect (gboolean enable_warnings,
 
 	g_type_init ();
 
-	client = g_object_new (TRACKER_TYPE_CLIENT, "timeout", timeout, 
-	                       "enable-warnings", enable_warnings, NULL);
+	client = g_object_new (TRACKER_TYPE_CLIENT, 
+	                       "timeout", timeout, 
+	                       "enable-warnings", enable_warnings,
+	                       "force-service", TRUE, NULL);
+
+	return client;
+}
+
+TrackerClient *
+tracker_connect_no_service_start (gboolean enable_warnings,
+                                  gint     timeout)
+{
+	TrackerClient *client;
+
+	g_type_init ();
+
+	client = g_object_new (TRACKER_TYPE_CLIENT,
+	                       "timeout", timeout, 
+	                       "enable-warnings", enable_warnings, 
+	                       "force-service", FALSE, NULL);
 
 	return client;
 }
diff --git a/src/libtracker-client/tracker.h b/src/libtracker-client/tracker.h
index a98eb12..180d13d 100644
--- a/src/libtracker-client/tracker.h
+++ b/src/libtracker-client/tracker.h
@@ -105,6 +105,8 @@ gchar *        tracker_sparql_escape                       (const gchar
 
 TrackerClient *tracker_connect                             (gboolean                enable_warnings,
                                                             gint                    timeout);
+TrackerClient *tracker_connect_no_service_start            (gboolean                enable_warnings,
+                                                            gint                    timeout);
 void           tracker_disconnect                          (TrackerClient          *client);
 
 /* Synchronous API */
diff --git a/src/plugins/evolution/tracker-evolution-plugin.c b/src/plugins/evolution/tracker-evolution-plugin.c
index d2037b5..22237d9 100644
--- a/src/plugins/evolution/tracker-evolution-plugin.c
+++ b/src/plugins/evolution/tracker-evolution-plugin.c
@@ -119,6 +119,18 @@ G_DEFINE_TYPE (TrackerEvolutionPlugin, tracker_evolution_plugin, TRACKER_TYPE_MI
  * during registration of accounts and folders). I know this is cruel. I know. */
 
 typedef struct {
+	TrackerClient *client;
+	gchar *sparql;
+	gboolean commit;
+	gint prio;
+} PoolItem;
+
+typedef struct {
+	GThreadPool *pool;
+	gboolean can_die;
+} ThreadPool;
+
+typedef struct {
 	TrackerEvolutionPlugin *self; /* weak */
 	guint64 last_checkout;
 } ClientRegistry;
@@ -191,7 +203,7 @@ static GQueue *many_queue = NULL;
 static TrackerEvolutionPlugin *manager = NULL;
 static GStaticRecMutex glock = G_STATIC_REC_MUTEX_INIT;
 static guint register_count = 0;
-static GThreadPool *pool = NULL;
+static ThreadPool *pool = NULL;
 
 /* Prototype declarations */
 static void register_account (TrackerEvolutionPlugin *self, EAccount *account);
@@ -307,56 +319,83 @@ folder_registry_new (const gchar *account_uri,
 	return registry;
 }
 
-typedef struct {
-	TrackerEvolutionPlugin *self;
-	gchar *sparql;
-	gboolean commit;
-} PoolItem;
 
 static void
 exec_update (gpointer data, gpointer user_data)
 {
+	ThreadPool *pool = user_data;
 	PoolItem *item = data;
-	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (item->self);
 
-	g_static_rec_mutex_lock (priv->mutex);
-
-	if (priv->client) {
+	if (!pool->can_die) {
 		GError *error = NULL;
 
 		if (item->commit) {
-			tracker_resources_batch_commit (priv->client, &error);
+			tracker_resources_batch_commit (item->client, &error);
 		} else {
-			tracker_resources_batch_sparql_update (priv->client, item->sparql, &error);
+			tracker_resources_batch_sparql_update (item->client, item->sparql, &error);
 		}
 
 		if (error) {
-			g_warning ("Error updating data: %s\n", error->message);
+			/* g_warning ("Error updating data: %s\n", error->message); */
 			g_error_free (error);
 		}
+		/* Don't hammer DBus too much, else Evolution's UI sometimes becomes slugish
+		 * due to a dbus_watch_handle call on its mainloop */
+
+		g_usleep (300);
+	} else {
+		if (g_thread_pool_unprocessed (pool->pool) == 0) {
+			g_thread_pool_free (pool->pool, TRUE, TRUE);
+			g_free (pool);
+		}
 	}
-	g_static_rec_mutex_unlock (priv->mutex);
 
 	g_free (item->sparql);
-	g_object_unref (item->self);
+	g_object_unref (item->client);
 	g_slice_free (PoolItem, item);
 }
 
+static gint 
+pool_sort_func (gconstpointer a,
+                gconstpointer b,
+                gpointer user_data)
+{
+	PoolItem *item_a = (PoolItem *) a;
+	PoolItem *item_b = (PoolItem *) b;
+
+	return item_a->prio - item_b->prio;
+}
+
+static ThreadPool*
+pool_new (void)
+{
+	ThreadPool *wrap = g_new0 (ThreadPool, 1);
+
+	wrap->pool = g_thread_pool_new (exec_update, wrap, 1, FALSE, NULL);
+	g_thread_pool_set_sort_function (wrap->pool, pool_sort_func, NULL);
+	wrap->can_die = FALSE;
+
+	return wrap;
+}
+
 static void
-send_sparql_update (TrackerEvolutionPlugin *self, const gchar *sparql)
+send_sparql_update (TrackerEvolutionPlugin *self, const gchar *sparql, gint prio)
 {
-	PoolItem *item = g_slice_new (PoolItem);
+	TrackerEvolutionPluginPrivate *priv = TRACKER_EVOLUTION_PLUGIN_GET_PRIVATE (self);
 
-	if (!pool) {
-		pool = g_thread_pool_new (exec_update, NULL, 1, FALSE, NULL);
-	}
+	if (priv->client) {
+		PoolItem *item = g_slice_new (PoolItem);
 
-	item->commit = FALSE;
-	item->self = g_object_ref (self);
-	item->sparql = g_strdup (sparql);
+		if (!pool)
+			pool = pool_new ();
 
-	g_thread_pool_push (pool, item, NULL);
+		item->prio = prio;
+		item->commit = FALSE;
+		item->client = g_object_ref (priv->client);
+		item->sparql = g_strdup (sparql);
 
+		g_thread_pool_push (pool->pool, item, NULL);
+	}
 }
 
 static void
@@ -374,22 +413,21 @@ send_sparql_commit (TrackerEvolutionPlugin *self, gboolean update)
 			                                 "INSERT INTO <"DATASOURCE_URN"> { <" DATASOURCE_URN "> nie:contentLastModified \"%s\" }",
 			                                 date_s);
 
-			send_sparql_update (self, update);
+			send_sparql_update (self, update, 0);
 
 			g_free (update);
 			g_free (date_s);
 		}
 
+		if (!pool)
+			pool = pool_new ();
 
-		if (!pool) {
-			pool = g_thread_pool_new (exec_update, NULL, 1, FALSE, NULL);
-		}
-
+		item->prio = 0;
 		item->commit = TRUE;
-		item->self = g_object_ref (self);
+		item->client = g_object_ref (priv->client);
 		item->sparql = NULL;
 
-		g_thread_pool_push (pool, item, NULL);
+		g_thread_pool_push (pool->pool, item, NULL);
 	}
 }
 
@@ -737,7 +775,7 @@ on_folder_summary_changed (CamelFolder *folder,
 
 			tracker_sparql_builder_insert_close (sparql);
 
-			send_sparql_update (info->self, tracker_sparql_builder_get_result (sparql));
+			send_sparql_update (info->self, tracker_sparql_builder_get_result (sparql), 100);
 
 			g_object_set (info->self, "progress",
 			              (gdouble) i / merged->len,
@@ -778,7 +816,7 @@ on_folder_summary_changed (CamelFolder *folder,
 			                        (char*) changes->uid_removed->pdata[i]);
 		}
 
-		send_sparql_update (info->self, sparql->str);
+		send_sparql_update (info->self, sparql->str, 100);
 		g_string_free (sparql, TRUE);
 	}
 
@@ -858,7 +896,7 @@ many_idle_handler (gpointer user_data)
 			              NULL);
 #endif
 
-			send_sparql_update (user_data, query);
+			send_sparql_update (user_data, query, 0);
 		} else {
 			/* Performance improvement: remove all that had
 			 * this disconnected registrar from the queue */
@@ -1085,14 +1123,6 @@ introduce_walk_folders_in_folder (TrackerEvolutionPlugin *self,
 				}
 
 				if (count >= MAX_BEFORE_SEND) {
-
-					/* Yield per MAX_BEFORE_SEND. This function is
-					 * called as a result of a DBus call, so it runs
-					 * in the mainloop. Therefore, yield he mainloop
-					 * sometimes, indeed */
-
-					g_main_context_iteration (NULL, TRUE);
-
 					more = TRUE;
 					break;
 				}
@@ -1224,14 +1254,6 @@ introduce_store_deal_with_deleted (TrackerEvolutionPlugin *self,
 			                                              mailbox, uid));
 
 			if (count > MAX_BEFORE_SEND) {
-
-				/* Yield per MAX_BEFORE_SEND. This function is
-				 * called as a result of a DBus call, so it runs
-				 * in the mainloop. Therefore, yield he mainloop
-				 * sometimes, indeed */
-
-				g_main_context_iteration (NULL, TRUE);
-
 				more = TRUE;
 				break;
 			}
@@ -1255,7 +1277,7 @@ introduce_store_deal_with_deleted (TrackerEvolutionPlugin *self,
 
 			g_string_append_c (sparql, '}');
 
-			send_sparql_update (self, sparql->str);
+			send_sparql_update (self, sparql->str, 100);
 			g_string_free (sparql, TRUE);
 
 		}
@@ -1712,7 +1734,7 @@ register_client_second_half (ClientRegistry *info)
 	if (info->last_checkout < too_old) {
 
 		send_sparql_update (info->self, "DELETE FROM <"DATASOURCE_URN"> { ?s a rdfs:Resource } "
-		                    "WHERE { ?s nie:dataSource <" DATASOURCE_URN "> }");
+		                    "WHERE { ?s nie:dataSource <" DATASOURCE_URN "> }", 0);
 		send_sparql_commit (info->self, FALSE);
 
 		info->last_checkout = 0;
@@ -2058,7 +2080,7 @@ disable_plugin (void)
 	}
 
 	if (pool) {
-		g_thread_pool_free (pool, FALSE, TRUE);
+		pool->can_die = TRUE;
 		pool = NULL;
 	}
 }
@@ -2111,14 +2133,20 @@ name_owner_changed_cb (DBusGProxy *proxy,
 	if (g_strcmp0 (name, TRACKER_SERVICE) == 0) {
 		 if (tracker_is_empty_string (new_owner) && !tracker_is_empty_string (old_owner)) {
 			if (priv->client) {
-				 tracker_disconnect (priv->client);
-				 priv->client = NULL; 
+				TrackerClient *client = priv->client;
+				priv->client = NULL; 
+
+				if (pool) {
+					pool->can_die = TRUE;
+					pool = NULL;
+				}
+				 tracker_disconnect (client);
 			}
 		}
 
 		if (tracker_is_empty_string (old_owner) && !tracker_is_empty_string (new_owner)) {
 			if (!priv->client) {
-				priv->client = tracker_connect (FALSE, G_MAXINT);
+				priv->client = tracker_connect_no_service_start (FALSE, G_MAXINT);
 			}
 			register_client (user_data);
 		}
@@ -2178,8 +2206,15 @@ tracker_evolution_plugin_finalize (GObject *plugin)
 	g_object_unref (priv->accounts);
 
 	if (priv->client) {
-		tracker_disconnect (priv->client);
+		TrackerClient *client = priv->client;
 		priv->client = NULL;
+
+		if (pool) {
+			pool->can_die = TRUE;
+			pool = NULL;
+		}
+
+		tracker_disconnect (client);
 	}
 	g_static_rec_mutex_unlock (priv->mutex);
 
@@ -2303,7 +2338,7 @@ miner_started (TrackerMiner *miner)
 	g_static_rec_mutex_lock (priv->mutex);
 
 	if (!priv->client) {
-		priv->client = tracker_connect (FALSE, G_MAXINT);
+		priv->client = tracker_connect_no_service_start (FALSE, G_MAXINT);
 	}
 
 	g_static_rec_mutex_unlock (priv->mutex);
@@ -2346,9 +2381,16 @@ miner_paused (TrackerMiner *miner)
 	g_static_rec_mutex_lock (priv->mutex);
 
 	if (priv->client) {
-		tracker_disconnect (priv->client);
+		TrackerClient *client = priv->client;
 		priv->client = NULL;
 
+		if (pool) {
+			pool->can_die = TRUE;
+			pool = NULL;
+		}
+
+		tracker_disconnect (client);
+
 		/* By setting this to NULL, events will still be catched by our
 		 * handlers, but the send_sparql_* calls will just ignore it.
 		 * This is fine as a solution (at least for now). It allows us
@@ -2398,7 +2440,7 @@ miner_resumed (TrackerMiner *miner)
 	priv->of_total = 0;
 
 	if (!priv->client) {
-		priv->client = tracker_connect (FALSE, G_MAXINT);
+		priv->client = tracker_connect_no_service_start (FALSE, G_MAXINT);
 	}
 	g_static_rec_mutex_unlock (priv->mutex);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]