[Xfce4-commits] <tumbler:pre-unmount> Cancel all URIs when the GMount they reside in is about to be unmounted.

Jannis Pohlmann noreply at xfce.org
Thu Oct 15 16:26:02 CEST 2009


Updating branch refs/heads/pre-unmount
         to 965b17ae8dc8090e359161b5e6af2df2eb2cf062 (commit)
       from 07b85dd85a3039a52ddf23683ba9a5c32bfb7118 (commit)

commit 965b17ae8dc8090e359161b5e6af2df2eb2cf062
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Thu Oct 15 16:22:42 2009 +0200

    Cancel all URIs when the GMount they reside in is about to be unmounted.
    
    This is done so that people don't have to wait so long until they can
    take out their removable media while the thumbnailer is busy on the
    device.

 tumblerd/tumbler-group-scheduler.c |   54 ++++++++++++++++++++++++++++++++++
 tumblerd/tumbler-lifo-scheduler.c  |   57 ++++++++++++++++++++++++++++++++++-
 tumblerd/tumbler-scheduler.c       |   13 ++++++++
 tumblerd/tumbler-scheduler.h       |   12 +++++--
 tumblerd/tumbler-service.c         |   44 +++++++++++++++++++++++++++
 5 files changed, 174 insertions(+), 6 deletions(-)

diff --git a/tumblerd/tumbler-group-scheduler.c b/tumblerd/tumbler-group-scheduler.c
index 7c4cdf0..d7b6b68 100644
--- a/tumblerd/tumbler-group-scheduler.c
+++ b/tumblerd/tumbler-group-scheduler.c
@@ -64,6 +64,8 @@ static void tumbler_group_scheduler_push              (TumblerScheduler
                                                        TumblerSchedulerRequest   *request);
 static void tumbler_group_scheduler_unqueue           (TumblerScheduler          *scheduler,
                                                        guint                      handle);
+static void tumbler_group_scheduler_cancel_by_mount   (TumblerScheduler          *scheduler,
+                                                       GMount                    *mount);
 static void tumbler_group_scheduler_finish_request    (TumblerGroupScheduler     *scheduler,
                                                        TumblerSchedulerRequest   *request);
 static void tumbler_group_scheduler_unqueue_request   (TumblerSchedulerRequest   *request,
@@ -141,6 +143,7 @@ tumbler_group_scheduler_iface_init (TumblerSchedulerIface *iface)
 {
   iface->push = tumbler_group_scheduler_push;
   iface->unqueue = tumbler_group_scheduler_unqueue;
+  iface->cancel_by_mount = tumbler_group_scheduler_cancel_by_mount;
 }
 
 
@@ -282,6 +285,53 @@ tumbler_group_scheduler_unqueue (TumblerScheduler *scheduler,
 
 
 static void
+tumbler_group_scheduler_cancel_by_mount (TumblerScheduler *scheduler,
+                                        GMount           *mount)
+{
+  TumblerSchedulerRequest *request;
+  TumblerGroupScheduler   *group_scheduler = TUMBLER_GROUP_SCHEDULER (scheduler);
+  GFile                   *mount_point;
+  GFile                   *file;
+  GList                   *iter;
+  guint                    n;
+
+  g_return_if_fail (TUMBLER_IS_GROUP_SCHEDULER (scheduler));
+  g_return_if_fail (G_IS_MOUNT (mount));
+
+  /* determine the root mount point */
+  mount_point = g_mount_get_root (mount);
+
+  g_mutex_lock (group_scheduler->mutex);
+
+  /* iterate over all requests */
+  for (iter = group_scheduler->requests; iter != NULL; iter = iter->next)
+    {
+      request = iter->data;
+
+      /* iterate over all request URIs */
+      for (n = 0; request->uris != NULL && request->uris[n] != NULL; ++n)
+        {
+          /* determine the enclosing mount for the file */
+          file = g_file_new_for_uri (request->uris[n]);
+
+          /* cancel the URI if it lies of the mount point */
+          if (g_file_has_prefix (file, mount_point))
+            g_cancellable_cancel (request->cancellables[n]);
+
+          /* release the file object */
+          g_object_unref (file);
+        }
+    }
+
+  g_mutex_unlock (group_scheduler->mutex);
+
+  /* release the mount point */
+  g_object_unref (mount_point);
+}
+
+
+
+static void
 tumbler_group_scheduler_finish_request (TumblerGroupScheduler *scheduler,
                                         TumblerSchedulerRequest   *request)
 {
@@ -414,6 +464,10 @@ tumbler_group_scheduler_thread (gpointer data,
         }
       g_mutex_unlock (scheduler->mutex);
 
+      /* ignore the the URI if has been cancelled already */
+      if (g_cancellable_is_cancelled (request->cancellables[n]))
+        continue;
+
       /* create a file infor for the current URI */
       info = tumbler_file_info_new (request->uris[n]);
       uri_needs_update = FALSE;
diff --git a/tumblerd/tumbler-lifo-scheduler.c b/tumblerd/tumbler-lifo-scheduler.c
index 2c25517..2501f92 100644
--- a/tumblerd/tumbler-lifo-scheduler.c
+++ b/tumblerd/tumbler-lifo-scheduler.c
@@ -57,6 +57,8 @@ static void tumbler_lifo_scheduler_push              (TumblerScheduler
                                                       TumblerSchedulerRequest   *request);
 static void tumbler_lifo_scheduler_unqueue           (TumblerScheduler          *scheduler,
                                                       guint                      handle);
+static void tumbler_lifo_scheduler_cancel_by_mount   (TumblerScheduler          *scheduler,
+                                                      GMount                    *mount);
 static void tumbler_lifo_scheduler_finish_request    (TumblerLifoScheduler *scheduler,
                                                       TumblerSchedulerRequest   *request);
 static void tumbler_lifo_scheduler_unqueue_request   (TumblerSchedulerRequest   *request,
@@ -123,6 +125,7 @@ tumbler_lifo_scheduler_iface_init (TumblerSchedulerIface *iface)
 {
   iface->push = tumbler_lifo_scheduler_push;
   iface->unqueue = tumbler_lifo_scheduler_unqueue;
+  iface->cancel_by_mount = tumbler_lifo_scheduler_cancel_by_mount;
 }
 
 
@@ -239,8 +242,7 @@ static void
 tumbler_lifo_scheduler_unqueue (TumblerScheduler *scheduler,
                                 guint             handle)
 {
-  TumblerLifoScheduler *lifo_scheduler = 
-    TUMBLER_LIFO_SCHEDULER (scheduler);
+  TumblerLifoScheduler *lifo_scheduler = TUMBLER_LIFO_SCHEDULER (scheduler);
 
   g_return_if_fail (TUMBLER_IS_LIFO_SCHEDULER (scheduler));
   g_return_if_fail (handle != 0);
@@ -258,6 +260,53 @@ tumbler_lifo_scheduler_unqueue (TumblerScheduler *scheduler,
 
 
 static void
+tumbler_lifo_scheduler_cancel_by_mount (TumblerScheduler *scheduler,
+                                        GMount           *mount)
+{
+  TumblerSchedulerRequest *request;
+  TumblerLifoScheduler    *lifo_scheduler = TUMBLER_LIFO_SCHEDULER (scheduler);
+  GFile                   *mount_point;
+  GFile                   *file;
+  GList                   *iter;
+  guint                    n;
+
+  g_return_if_fail (TUMBLER_IS_LIFO_SCHEDULER (scheduler));
+  g_return_if_fail (G_IS_MOUNT (mount));
+
+  /* determine the root mount point */
+  mount_point = g_mount_get_root (mount);
+
+  g_mutex_lock (lifo_scheduler->mutex);
+
+  /* iterate over all requests */
+  for (iter = lifo_scheduler->requests; iter != NULL; iter = iter->next)
+    {
+      request = iter->data;
+
+      /* iterate over all request URIs */
+      for (n = 0; request->uris != NULL && request->uris[n] != NULL; ++n)
+        {
+          /* determine the enclosing mount for the file */
+          file = g_file_new_for_uri (request->uris[n]);
+
+          /* cancel the URI if it lies of the mount point */
+          if (g_file_has_prefix (file, mount_point))
+            g_cancellable_cancel (request->cancellables[n]);
+
+          /* release the file object */
+          g_object_unref (file);
+        }
+    }
+
+  g_mutex_unlock (lifo_scheduler->mutex);
+
+  /* release the mount point */
+  g_object_unref (mount_point);
+}
+
+
+
+static void
 tumbler_lifo_scheduler_finish_request (TumblerLifoScheduler *scheduler,
                                        TumblerSchedulerRequest   *request)
 {
@@ -348,6 +397,10 @@ tumbler_lifo_scheduler_thread (gpointer data,
         }
       g_mutex_unlock (scheduler->mutex);
 
+      /* ignore the the URI if has been cancelled already */
+      if (g_cancellable_is_cancelled (request->cancellables[n]))
+        continue;
+
       /* create a file info for the current URI */
       info = tumbler_file_info_new (request->uris[n]);
       uri_needs_update = FALSE;
diff --git a/tumblerd/tumbler-scheduler.c b/tumblerd/tumbler-scheduler.c
index 055619c..60aad77 100644
--- a/tumblerd/tumbler-scheduler.c
+++ b/tumblerd/tumbler-scheduler.c
@@ -200,6 +200,19 @@ tumbler_scheduler_unqueue (TumblerScheduler *scheduler,
 
 
 void
+tumbler_scheduler_cancel_by_mount (TumblerScheduler *scheduler,
+                                   GMount           *mount)
+{
+  g_return_if_fail (TUMBLER_IS_SCHEDULER (scheduler));
+  g_return_if_fail (G_IS_MOUNT (mount));
+  g_return_if_fail (TUMBLER_SCHEDULER_GET_IFACE (scheduler)->cancel_by_mount != NULL);
+
+  TUMBLER_SCHEDULER_GET_IFACE (scheduler)->cancel_by_mount (scheduler, mount);
+}
+
+
+
+void
 tumbler_scheduler_take_request (TumblerScheduler        *scheduler,
                                 TumblerSchedulerRequest *request)
 {
diff --git a/tumblerd/tumbler-scheduler.h b/tumblerd/tumbler-scheduler.h
index 3eaacac..d92a0c7 100644
--- a/tumblerd/tumbler-scheduler.h
+++ b/tumblerd/tumbler-scheduler.h
@@ -54,10 +54,12 @@ struct _TumblerSchedulerIface
                     guint                    handle);
 
   /* virtual methods */
-  void (*push)     (TumblerScheduler        *scheduler,
-                    TumblerSchedulerRequest *request);
-  void (*unqueue)  (TumblerScheduler        *scheduler,
-                    guint                    handle);
+  void (*push)            (TumblerScheduler        *scheduler,
+                           TumblerSchedulerRequest *request);
+  void (*unqueue)         (TumblerScheduler        *scheduler,
+                           guint                    handle);
+  void (*cancel_by_mount) (TumblerScheduler        *scheduler,
+                           GMount                  *mount);
 };
 
 GType                    tumbler_scheduler_get_type              (void) G_GNUC_CONST;
@@ -66,6 +68,8 @@ void                     tumbler_scheduler_push                  (TumblerSchedul
                                                                   TumblerSchedulerRequest *request);
 void                     tumbler_scheduler_unqueue               (TumblerScheduler        *scheduler,
                                                                   guint                    handle);
+void                     tumbler_scheduler_cancel_by_mount       (TumblerScheduler        *scheduler,
+                                                                  GMount                  *mount);
 gchar*                   tumbler_scheduler_get_name              (TumblerScheduler        *scheduler);
 void                     tumbler_scheduler_take_request          (TumblerScheduler        *scheduler,
                                                                   TumblerSchedulerRequest *request);
diff --git a/tumblerd/tumbler-service.c b/tumblerd/tumbler-service.c
index 3280798..6f9a05a 100644
--- a/tumblerd/tumbler-service.c
+++ b/tumblerd/tumbler-service.c
@@ -26,6 +26,8 @@
 #include <glib/gi18n.h>
 #include <glib-object.h>
 
+#include <gio/gio.h>
+
 #include <dbus/dbus.h>
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
@@ -39,10 +41,14 @@
 #include <tumblerd/tumbler-group-scheduler.h>
 #include <tumblerd/tumbler-utils.h>
 
+
+
 #define THUMBNAILER_PATH    "/org/freedesktop/thumbnails/Thumbnailer1"
 #define THUMBNAILER_SERVICE "org.freedesktop.thumbnails.Thumbnailer1"
 #define THUMBNAILER_IFACE   "org.freedesktop.thumbnails.Thumbnailer1"
 
+
+
 /* signal identifiers */
 enum
 {
@@ -92,6 +98,9 @@ static void tumbler_service_scheduler_started  (TumblerScheduler *scheduler,
                                                 guint             handle,
                                                 const gchar      *origin,
                                                 TumblerService   *service);
+static void tumbler_service_pre_unmount        (TumblerService   *service,
+                                                GMount           *mount,
+                                                GVolumeMonitor   *monitor);
 
 
 
@@ -108,6 +117,8 @@ struct _TumblerService
   TumblerRegistry  *registry;
   GMutex           *mutex;
   GList            *schedulers;
+
+  GVolumeMonitor   *volume_monitor;
 };
 
 
@@ -205,6 +216,10 @@ tumbler_service_init (TumblerService *service)
 {
   service->mutex = g_mutex_new ();
   service->schedulers = NULL;
+
+  service->volume_monitor = g_volume_monitor_get ();
+  g_signal_connect_swapped (service->volume_monitor, "mount-pre-unmount", 
+                            G_CALLBACK (tumbler_service_pre_unmount), service);
 }
 
 
@@ -257,6 +272,13 @@ tumbler_service_finalize (GObject *object)
 {
   TumblerService *service = TUMBLER_SERVICE (object);
 
+  /* disconnect from the volume monitor */
+  g_signal_handlers_disconnect_matched (service->volume_monitor, G_SIGNAL_MATCH_DATA,
+                                        0, 0, NULL, NULL, service);
+
+  /* release the volume monitor */
+  g_object_unref (service->volume_monitor);
+
   /* release all schedulers and the scheduler list */
   g_list_foreach (service->schedulers, (GFunc) g_object_unref, NULL);
   g_list_free (service->schedulers);
@@ -473,6 +495,27 @@ tumbler_service_scheduler_started (TumblerScheduler *scheduler,
 
 
 
+static void
+tumbler_service_pre_unmount (TumblerService *service,
+                             GMount         *mount,
+                             GVolumeMonitor *volume_monitor)
+{
+  GList *iter;
+
+  g_return_if_fail (TUMBLER_IS_SERVICE (service));
+  g_return_if_fail (G_IS_MOUNT (mount));
+  g_return_if_fail (volume_monitor == service->volume_monitor);
+
+  g_mutex_lock (service->mutex);
+
+  for (iter = service->schedulers; iter != NULL; ++iter)
+    tumbler_scheduler_cancel_by_mount (iter->data, mount);
+
+  g_mutex_unlock (service->mutex);
+}
+
+
+
 TumblerService *
 tumbler_service_new (DBusGConnection *connection,
                      TumblerRegistry *registry)
@@ -673,6 +716,7 @@ tumbler_service_get_supported (TumblerService        *service,
 }
 
 
+
 void
 tumbler_service_get_schedulers (TumblerService        *service,
                                 DBusGMethodInvocation *context)



More information about the Xfce4-commits mailing list