[tracker/libtracker-miner-improved-pausing: 1/2] libtracker-miner: Added APIs for pausing miners during process life time



commit 7595ee1df6bc0f4944731b5a569458d3ca47aa5c
Author: Martyn Russell <martyn lanedo com>
Date:   Mon May 16 12:22:11 2011 +0100

    libtracker-miner: Added APIs for pausing miners during process life time
    
    This adds:
     - tracker_miner_pause_for_process()
     - tracker_miner_manager_pause_for_process()
    
    This also adds the dbus equivalent APIs.

 data/dbus/tracker-miner.xml                  |    6 +
 src/libtracker-miner/tracker-miner-manager.c |   74 ++++++++++
 src/libtracker-miner/tracker-miner-manager.h |    4 +
 src/libtracker-miner/tracker-miner-object.c  |  190 +++++++++++++++++++++++---
 src/libtracker-miner/tracker-miner-object.h  |    3 +
 5 files changed, 256 insertions(+), 21 deletions(-)
---
diff --git a/data/dbus/tracker-miner.xml b/data/dbus/tracker-miner.xml
index 901943f..00bb5f2 100644
--- a/data/dbus/tracker-miner.xml
+++ b/data/dbus/tracker-miner.xml
@@ -26,6 +26,12 @@
       <arg type="s" name="reason" direction="in" />
       <arg type="i" name="cookie" direction="out" />
     </method>
+    <method name="PauseForProcess">
+      <annotation name="org.freedesktop.DBus.GLib.Async"  value="true"/>
+      <arg type="s" name="application" direction="in" />
+      <arg type="s" name="reason" direction="in" />
+      <arg type="i" name="cookie" direction="out" />
+    </method>
     <method name="Resume">
       <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/>
       <arg type="i" name="cookie" direction="in" />
diff --git a/src/libtracker-miner/tracker-miner-manager.c b/src/libtracker-miner/tracker-miner-manager.c
index e1cb7dd..ab981a0 100644
--- a/src/libtracker-miner/tracker-miner-manager.c
+++ b/src/libtracker-miner/tracker-miner-manager.c
@@ -895,6 +895,80 @@ tracker_miner_manager_pause (TrackerMinerManager *manager,
 }
 
 /**
+ * tracker_miner_manager_pause_for_process:
+ * @manager: a #TrackerMinerManager.
+ * @miner: miner reference
+ * @reason: reason to pause
+ * @cookie: return location for the pause cookie ID
+ *
+ * This function operates exactly the same way as
+ * tracker_miner_manager_pause() with the exception that if the calling
+ * process dies, the pause is resumed. This API is useful for cases
+ * where the calling process has a risk of crashing without resuming
+ * the pause.
+ *
+ * Returns: %TRUE if the miner was paused successfully, otherwise
+ * %FALSE.
+ *
+ * Since: 0.10.14
+ **/
+gboolean
+tracker_miner_manager_pause_for_process (TrackerMinerManager *manager,
+                                         const gchar         *miner,
+                                         const gchar         *reason,
+                                         guint32             *cookie)
+{
+	GDBusProxy *proxy;
+	const gchar *app_name;
+	GError *error = NULL;
+	GVariant *v;
+
+	g_return_val_if_fail (TRACKER_IS_MINER_MANAGER (manager), FALSE);
+	g_return_val_if_fail (miner != NULL, FALSE);
+	g_return_val_if_fail (reason != NULL, FALSE);
+
+	proxy = find_miner_proxy (manager, miner, TRUE);
+
+	if (!proxy) {
+		g_critical ("No D-Bus proxy found for miner '%s'", miner);
+		return FALSE;
+	}
+
+	/* Find a reasonable app name */
+	app_name = g_get_application_name ();
+
+	if (!app_name) {
+		app_name = g_get_prgname ();
+	}
+
+	if (!app_name) {
+		app_name = "TrackerMinerManager client";
+	}
+
+	v = g_dbus_proxy_call_sync (proxy,
+	                            "PauseForProcess",
+	                            g_variant_new ("(ss)", app_name, reason),
+	                            G_DBUS_CALL_FLAGS_NONE,
+	                            -1,
+	                            NULL,
+	                            &error);
+
+	if (error) {
+		g_critical ("Could not pause miner '%s': %s", miner, error->message);
+		g_error_free (error);
+		return FALSE;
+	}
+
+	if (cookie) {
+		g_variant_get (v, "(i)", cookie);
+	}
+
+	g_variant_unref (v);
+
+	return TRUE;
+}
+
+/**
  * tracker_miner_manager_resume:
  * @manager: a #TrackerMinerManager
  * @miner: miner reference
diff --git a/src/libtracker-miner/tracker-miner-manager.h b/src/libtracker-miner/tracker-miner-manager.h
index ea3e3e6..83cd3b9 100644
--- a/src/libtracker-miner/tracker-miner-manager.h
+++ b/src/libtracker-miner/tracker-miner-manager.h
@@ -106,6 +106,10 @@ gboolean             tracker_miner_manager_pause              (TrackerMinerManag
                                                                const gchar          *miner,
                                                                const gchar          *reason,
                                                                guint32              *cookie);
+gboolean             tracker_miner_manager_pause_for_process  (TrackerMinerManager  *manager,
+                                                               const gchar          *miner,
+                                                               const gchar          *reason,
+                                                               guint32              *cookie);
 gboolean             tracker_miner_manager_resume             (TrackerMinerManager  *manager,
                                                                const gchar          *miner,
                                                                guint32               cookie);
diff --git a/src/libtracker-miner/tracker-miner-object.c b/src/libtracker-miner/tracker-miner-object.c
index 3d70ac5..06dba05 100644
--- a/src/libtracker-miner/tracker-miner-object.c
+++ b/src/libtracker-miner/tracker-miner-object.c
@@ -83,6 +83,11 @@ static const gchar introspection_xml[] =
   "      <arg type='s' name='reason' direction='in' />"
   "      <arg type='i' name='cookie' direction='out' />"
   "    </method>"
+  "    <method name='PauseForProcess'>"
+  "      <arg type='s' name='application' direction='in' />"
+  "      <arg type='s' name='reason' direction='in' />"
+  "      <arg type='i' name='cookie' direction='out' />"
+  "    </method>"
   "    <method name='Resume'>"
   "      <arg type='i' name='cookie' direction='in' />"
   "    </method>"
@@ -121,6 +126,8 @@ typedef struct {
 	gint cookie;
 	gchar *application;
 	gchar *reason;
+	gchar *watch_name;
+	guint watch_name_id;
 } PauseData;
 
 enum {
@@ -158,7 +165,9 @@ static gboolean   miner_initable_init          (GInitable              *initable
                                                 GError                **error);
 static void       pause_data_destroy           (gpointer                data);
 static PauseData *pause_data_new               (const gchar            *application,
-                                                const gchar            *reason);
+                                                const gchar            *reason,
+                                                const gchar            *watch_name,
+                                                guint                   watch_name_id);
 static void       handle_method_call           (GDBusConnection        *connection,
                                                 const gchar            *sender,
                                                 const gchar            *object_path,
@@ -617,7 +626,9 @@ miner_get_property (GObject    *object,
 
 static PauseData *
 pause_data_new (const gchar *application,
-                const gchar *reason)
+                const gchar *reason,
+                const gchar *watch_name,
+                guint        watch_name_id)
 {
 	PauseData *data;
 	static gint cookie = 1;
@@ -627,6 +638,8 @@ pause_data_new (const gchar *application,
 	data->cookie = cookie++;
 	data->application = g_strdup (application);
 	data->reason = g_strdup (reason);
+	data->watch_name = g_strdup (watch_name);
+	data->watch_name_id = watch_name_id;
 
 	return data;
 }
@@ -638,6 +651,12 @@ pause_data_destroy (gpointer data)
 
 	pd = data;
 
+	if (pd->watch_name_id) {
+		g_bus_unwatch_name (pd->watch_name_id);
+	}
+
+	g_free (pd->watch_name);
+
 	g_free (pd->reason);
 	g_free (pd->application);
 
@@ -790,15 +809,58 @@ tracker_miner_get_n_pause_reasons (TrackerMiner *miner)
 	return g_hash_table_size (miner->private->pauses);
 }
 
+static void
+pause_process_disappeared_cb (GDBusConnection *connection,
+                              const gchar     *name,
+                              gpointer         user_data)
+{
+	TrackerMiner *miner;
+	PauseData *pd = NULL;
+	GError *error = NULL;
+	GHashTableIter iter;
+	gpointer key, value;
+
+	miner = user_data;
+
+	g_message ("Process with name:'%s' has disappeared", name);
+
+	g_hash_table_iter_init (&iter, miner->private->pauses);
+	while (g_hash_table_iter_next (&iter, &key, &value)) {
+		PauseData *pd_iter = value;
+
+		if (g_strcmp0 (name, pd_iter->watch_name) == 0) {
+			pd = pd_iter;
+			break;
+		}
+	}
+
+	if (!pd) {
+		g_critical ("Could not find PauseData for process with name:'%s'", name);
+		return;
+	}
+
+	/* Resume */
+	g_message ("Resuming pause associated with process");
+
+	tracker_miner_resume (miner, pd->cookie, &error);
+
+	if (error) {
+		g_warning ("Could not resume miner, %s", error->message);
+		g_error_free (error);
+	}
+}
+
 static gint
-tracker_miner_pause_internal (TrackerMiner  *miner,
-                              const gchar   *application,
-                              const gchar   *reason,
-                              GError       **error)
+miner_pause_internal (TrackerMiner  *miner,
+                      const gchar   *application,
+                      const gchar   *reason,
+                      const gchar   *calling_name,
+                      GError       **error)
 {
 	PauseData *pd;
 	GHashTableIter iter;
 	gpointer key, value;
+	guint watch_name_id = 0;
 
 	/* Check this is not a duplicate pause */
 	g_hash_table_iter_init (&iter, miner->private->pauses);
@@ -814,7 +876,18 @@ tracker_miner_pause_internal (TrackerMiner  *miner,
 		}
 	}
 
-	pd = pause_data_new (application, reason);
+	if (calling_name) {
+		g_message ("Watching process with name:'%s'", calling_name);
+		watch_name_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+		                                  calling_name,
+		                                  G_BUS_NAME_WATCHER_FLAGS_NONE,
+		                                  NULL,
+		                                  pause_process_disappeared_cb,
+		                                  miner,
+		                                  NULL);
+	}
+
+	pd = pause_data_new (application, reason, calling_name, watch_name_id);
 
 	g_hash_table_insert (miner->private->pauses,
 	                     GINT_TO_POINTER (pd->cookie),
@@ -869,7 +942,45 @@ tracker_miner_pause (TrackerMiner  *miner,
 		application = miner->private->name;
 	}
 
-	return tracker_miner_pause_internal (miner, application, reason, error);
+	return miner_pause_internal (miner, application, reason, NULL, error);
+}
+
+/**
+ * tracker_miner_pause_for_process:
+ * @miner: a #TrackerMiner
+ * @reason: reason to pause
+ * @error: (out callee-allocates) (transfer full) (allow-none): return location for errors
+ *
+ * This function operates exactly the same way as
+ * tracker_miner_pause() with the exception that if the calling
+ * process dies, the pause is resumed. This API is useful for cases
+ * where the calling process has a risk of crashing without resuming
+ * the pause.
+ *
+ * Returns: The pause cookie ID.
+ *
+ * Since: 0.10.14
+ **/
+gint
+tracker_miner_pause_for_process (TrackerMiner  *miner,
+                                 const gchar   *reason,
+                                 GError       **error)
+{
+	const gchar *application;
+
+	g_return_val_if_fail (TRACKER_IS_MINER (miner), -1);
+	g_return_val_if_fail (reason != NULL, -1);
+
+	application = g_get_application_name ();
+
+	if (!application) {
+		application = miner->private->name;
+	}
+
+	/* FIXME: We need to watch processes in /proc for non-dbus calls? */
+	gchar *calling_name = NULL;
+
+	return miner_pause_internal (miner, application, reason, calling_name, error);
 }
 
 /**
@@ -1090,7 +1201,48 @@ handle_method_call_pause (TrackerMiner          *miner,
 	                                        application,
 	                                        reason);
 
-	cookie = tracker_miner_pause_internal (miner, application, reason, &local_error);
+	cookie = miner_pause_internal (miner, application, reason, NULL, &local_error);
+	if (cookie == -1) {
+		tracker_dbus_request_end (request, local_error);
+
+		g_dbus_method_invocation_return_gerror (invocation, local_error);
+
+		g_error_free (local_error);
+
+		return;
+	}
+
+	tracker_dbus_request_end (request, NULL);
+	g_dbus_method_invocation_return_value (invocation,
+	                                       g_variant_new ("(i)", cookie));
+}
+
+static void
+handle_method_call_pause_for_process (TrackerMiner          *miner,
+                                      GDBusMethodInvocation *invocation,
+                                      GVariant              *parameters)
+{
+	GError *local_error = NULL;
+	gint cookie;
+	const gchar *application = NULL, *reason = NULL;
+	TrackerDBusRequest *request;
+
+	g_variant_get (parameters, "(&s&s)", &application, &reason);
+
+	tracker_gdbus_async_return_if_fail (application != NULL, invocation);
+	tracker_gdbus_async_return_if_fail (reason != NULL, invocation);
+
+	request = tracker_g_dbus_request_begin (invocation,
+	                                        "%s(application:'%s', reason:'%s')",
+	                                        __PRETTY_FUNCTION__,
+	                                        application,
+	                                        reason);
+
+	cookie = miner_pause_internal (miner,
+	                               application,
+	                               reason,
+	                               g_dbus_method_invocation_get_sender (invocation),
+	                               &local_error);
 	if (cookie == -1) {
 		tracker_dbus_request_end (request, local_error);
 
@@ -1207,23 +1359,19 @@ handle_method_call (GDBusConnection       *connection,
 
 	if (g_strcmp0 (method_name, "IgnoreNextUpdate") == 0) {
 		handle_method_call_ignore_next_update (miner, invocation, parameters);
-	} else
-	if (g_strcmp0 (method_name, "Resume") == 0) {
+	} else if (g_strcmp0 (method_name, "Resume") == 0) {
 		handle_method_call_resume (miner, invocation, parameters);
-	} else
-	if (g_strcmp0 (method_name, "Pause") == 0) {
+	} else if (g_strcmp0 (method_name, "Pause") == 0) {
 		handle_method_call_pause (miner, invocation, parameters);
-	} else
-	if (g_strcmp0 (method_name, "GetPauseDetails") == 0) {
+	} else if (g_strcmp0 (method_name, "PauseForProcess") == 0) {
+		handle_method_call_pause_for_process (miner, invocation, parameters);
+	} else if (g_strcmp0 (method_name, "GetPauseDetails") == 0) {
 		handle_method_call_get_pause_details (miner, invocation, parameters);
-	} else
-	if (g_strcmp0 (method_name, "GetRemainingTime") == 0) {
+	} else if (g_strcmp0 (method_name, "GetRemainingTime") == 0) {
 		handle_method_call_get_remaining_time (miner, invocation, parameters);
-	} else
-	if (g_strcmp0 (method_name, "GetProgress") == 0) {
+	} else if (g_strcmp0 (method_name, "GetProgress") == 0) {
 		handle_method_call_get_progress (miner, invocation, parameters);
-	} else
-	if (g_strcmp0 (method_name, "GetStatus") == 0) {
+	} else if (g_strcmp0 (method_name, "GetStatus") == 0) {
 		handle_method_call_get_status (miner, invocation, parameters);
 	} else {
 		g_assert_not_reached ();
diff --git a/src/libtracker-miner/tracker-miner-object.h b/src/libtracker-miner/tracker-miner-object.h
index 5602360..8ed8eb8 100644
--- a/src/libtracker-miner/tracker-miner-object.h
+++ b/src/libtracker-miner/tracker-miner-object.h
@@ -99,6 +99,9 @@ guint                    tracker_miner_get_n_pause_reasons (TrackerMiner
 gint                     tracker_miner_pause               (TrackerMiner         *miner,
                                                             const gchar          *reason,
                                                             GError              **error);
+gint                     tracker_miner_pause_for_process   (TrackerMiner         *miner,
+                                                            const gchar          *reason,
+                                                            GError              **error);
 gboolean                 tracker_miner_resume              (TrackerMiner         *miner,
                                                             gint                  cookie,
                                                             GError              **error);



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