gvfs r2261 - in trunk: . daemon/trashlib



Author: ryanl
Date: Fri Feb 27 23:04:31 2009
New Revision: 2261
URL: http://svn.gnome.org/viewvc/gvfs?rev=2261&view=rev

Log:
2009-02-27  Ryan Lortie  <desrt desrt ca>

        * daemon/trashlib/dirwatch.c:
        * daemon/trashlib/dirwatch.h:
        * daemon/trashlib/trashdir.c:
        * daemon/trashlib/trashitem.c:

        Use DirWatch only when watching (move broken manual-scan code out).
        Fix a bunch of leaks.



Modified:
   trunk/ChangeLog
   trunk/daemon/trashlib/dirwatch.c
   trunk/daemon/trashlib/dirwatch.h
   trunk/daemon/trashlib/trashdir.c
   trunk/daemon/trashlib/trashitem.c

Modified: trunk/daemon/trashlib/dirwatch.c
==============================================================================
--- trunk/daemon/trashlib/dirwatch.c	(original)
+++ trunk/daemon/trashlib/dirwatch.c	Fri Feb 27 23:04:31 2009
@@ -42,6 +42,13 @@
  * stops existing momentarily will (hopefully) always be reported.
  * The first call (if it happens) will always be to create().
  *
+ * check() is only ever called in response to a call to
+ * dir_watch_check() in which case it will be called only if the
+ * watched directory was marked as having existed before the check and
+ * is found to still exist.  This facilitates the checking that has to
+ * occur in that case (ie: check the contents of the directory to make
+ * sure that they are also unchanged).
+ *
  * This implementation is currently tweaked a bit for how GFileMonitor
  * currently works with inotify.  If GFileMonitor's implementation is
  * changed it might be a good idea to take another look at this code.
@@ -53,10 +60,10 @@
   GFile *topdir;
 
   DirWatchFunc create;
+  DirWatchFunc check;
   DirWatchFunc destroy;
   gpointer user_data;
   gboolean state;
-  gboolean active;
 
   DirWatch *parent;
 
@@ -172,6 +179,29 @@
 }
 
 static void
+dir_watch_recursive_check (gpointer user_data)
+{
+  DirWatch *watch = user_data;
+  gboolean exists;
+ 
+  exists = dir_exists (watch->directory);
+
+  if (watch->state && exists)
+    watch->check (watch->user_data);
+
+  else if (!watch->state && exists)
+    {
+      watch->state = TRUE;
+      dir_watch_created (watch);
+    }
+  else if (watch->state && !exists)
+    {
+      watch->state = FALSE;
+      dir_watch_destroyed (watch);
+    }
+}
+
+static void
 dir_watch_recursive_destroy (gpointer user_data)
 {
   DirWatch *watch = user_data;
@@ -193,8 +223,8 @@
 DirWatch *
 dir_watch_new (GFile        *directory,
                GFile        *topdir,
-               gboolean      watching,
                DirWatchFunc  create,
+               DirWatchFunc  check,
                DirWatchFunc  destroy,
                gpointer      user_data)
 {
@@ -202,6 +232,7 @@
 
   watch = g_slice_new0 (DirWatch);
   watch->create = create;
+  watch->check = check;
   watch->destroy = destroy;
   watch->user_data = user_data;
 
@@ -211,9 +242,7 @@
   /* the top directory always exists */
   if (g_file_equal (directory, topdir))
     {
-      if (watching)
-        dir_watch_created (watch);
-
+      dir_watch_created (watch);
       watch->state = TRUE;
     }
 
@@ -224,15 +253,13 @@
       parent = g_file_get_parent (directory);
       g_assert (parent != NULL);
 
-      watch->parent = dir_watch_new (parent, topdir, watching,
+      watch->parent = dir_watch_new (parent, topdir,
                                      dir_watch_recursive_create,
+                                     dir_watch_recursive_check,
                                      dir_watch_recursive_destroy,
                                      watch);
 
       g_object_unref (parent);
-
-      if (!watching)
-        watch->state = watch->parent->state && dir_exists (directory);
     }
 
   return watch;
@@ -250,68 +277,37 @@
       g_object_unref (watch->topdir);
 
       dir_watch_free (watch->parent);
-    }
-}
 
-void
-dir_watch_enable (DirWatch *watch)
-{
-  /* topdir always exists.  say so. */
-  if (watch->parent == NULL)
-    dir_watch_created (watch);
-
-  else
-    dir_watch_enable (watch->parent);
+      g_slice_free (DirWatch, watch);
+    }
 }
 
+/**
+ * dir_watch_check:
+ * @watch: a #DirWatch
+ *
+ * Emit missed events.
+ *
+ * This function is called on a DirWatch that might have missed events
+ * (because it is watching on an NFS mount, for example).
+ * 
+ * This function will manually check if any directories have come into
+ * or gone out of existence and will emit created or destroyed callbacks
+ * as appropriate.
+ *
+ * Additionally, if a directory is found to still exist, the checked
+ * callback will be emitted.
+ **/
 void
-dir_watch_disable (DirWatch *watch)
-{
-  if (watch->parent_monitor)
-    g_object_unref (watch->parent_monitor);
-
-  watch->parent_monitor = NULL;
-
-  if (watch->parent)
-    dir_watch_disable (watch->parent);
-}
-
-gboolean
-dir_watch_is_valid (DirWatch *watch)
+dir_watch_check (DirWatch *watch)
 {
-  return watch->state;
-}
-
-gboolean
-dir_watch_double_check (DirWatch *watch)
-{
-  gboolean old_state;
-
-  old_state = watch->state;
-
   if (watch->parent == NULL)
     {
-      g_assert (watch->state == TRUE);
-      return TRUE;
-    }
-
-  if (dir_watch_double_check (watch->parent))
-    {
-      if (dir_watch_is_valid (watch->parent))
-        watch->state = dir_exists (watch->directory);
-      else
-        watch->state = FALSE;
-
-
-      if (!old_state && watch->state && watch->parent_monitor)
-        dir_watch_created (watch);
-
-      else if (old_state && !watch->state && watch->parent_monitor)
-        dir_watch_destroyed (watch);
+      g_assert (watch->state);
 
-      else if (old_state || watch->state)
-        return TRUE;
+      watch->check (watch->user_data);
+      return;
     }
 
-  return FALSE;
+  dir_watch_check (watch->parent);
 }

Modified: trunk/daemon/trashlib/dirwatch.h
==============================================================================
--- trunk/daemon/trashlib/dirwatch.h	(original)
+++ trunk/daemon/trashlib/dirwatch.h	Fri Feb 27 23:04:31 2009
@@ -16,17 +16,12 @@
 
 DirWatch               *dir_watch_new           (GFile         *directory,
                                                  GFile         *topdir,
-                                                 gboolean       watching,
                                                  DirWatchFunc   create,
+                                                 DirWatchFunc   check,
                                                  DirWatchFunc   destroy,
                                                  gpointer       user_data);
 
-void                    dir_watch_enable        (DirWatch      *watch);
-void                    dir_watch_disable       (DirWatch      *watch);
-gboolean                dir_watch_double_check  (DirWatch      *watch);
-
-gboolean                dir_watch_is_valid      (DirWatch      *watch);
-gboolean                dir_watch_needs_update  (DirWatch      *watch);
+void                    dir_watch_check         (DirWatch      *watch);
 
 void                    dir_watch_free          (DirWatch      *watch);
 

Modified: trunk/daemon/trashlib/trashdir.c
==============================================================================
--- trunk/daemon/trashlib/trashdir.c	(original)
+++ trunk/daemon/trashlib/trashdir.c	Fri Feb 27 23:04:31 2009
@@ -8,6 +8,7 @@
 
 #include "trashdir.h"
 
+#include <sys/stat.h>
 #include <string.h>
 
 #include "dirwatch.h"
@@ -146,6 +147,10 @@
   else if (event_type == G_FILE_MONITOR_EVENT_DELETED)
     trash_root_remove_item (dir->root, file, dir->is_homedir);
 
+  else if (event_type == G_FILE_MONITOR_EVENT_PRE_UNMOUNT ||
+           event_type == G_FILE_MONITOR_EVENT_UNMOUNTED)
+    ;
+
   else
     {
       static gboolean already_did_warning;
@@ -168,6 +173,8 @@
       dirname = g_file_get_path (dir->directory);
       g_warning ("  dir: %s, file: %s, type: %d\n\n",
                  dirname, name, event_type);
+      g_free (dirname);
+      g_free (name);
     }
 
   trash_root_thaw (dir->root);
@@ -186,6 +193,14 @@
 }
 
 static void
+trash_dir_check (gpointer user_data)
+{
+  TrashDir *dir = user_data;
+
+  trash_dir_enumerate (dir);
+}
+
+static void
 trash_dir_destroyed (gpointer user_data)
 {
   TrashDir *dir = user_data;
@@ -201,6 +216,7 @@
 trash_dir_watch (TrashDir *dir)
 {
   g_assert (dir->monitor == NULL);
+  g_assert (dir->watch == NULL);
 
   /* start monitoring after a period of not monitoring.
    *
@@ -214,7 +230,7 @@
    *        toplevel items that need to be removed.
    *
    * in case 1, trash_dir_created() will be called from
-   * dir_watch_new().  it calls trash_dir_rescan() itself.
+   * dir_watch_new().  it calls trash_enumerate() itself.
    *
    * in case 2, no other function will be called and we must manually
    * call trash_dir_empty().
@@ -222,7 +238,11 @@
    * we can tell if case 1 happened because trash_dir_created() also
    * sets the dir->monitor.
    */
-  dir_watch_enable (dir->watch);
+  dir->watch = dir_watch_new (dir->directory, dir->topdir,
+                              trash_dir_created,
+                              trash_dir_check,
+                              trash_dir_destroyed,
+                              dir);
 
   if (dir->monitor == NULL)
     /* case 2 */
@@ -232,6 +252,8 @@
 void
 trash_dir_unwatch (TrashDir *dir)
 {
+  g_assert (dir->watch != NULL);
+
   /* stop monitoring.
    *
    * in all cases, we just fall silent.
@@ -243,19 +265,49 @@
       dir->monitor = NULL;
     }
 
-  dir_watch_disable (dir->watch);
+  dir_watch_free (dir->watch);
+  dir->watch = NULL;
 }
 
-void
-trash_dir_rescan (TrashDir *dir)
+static gboolean
+dir_exists (GFile *directory,
+            GFile *top_dir)
 {
-  if (dir_watch_double_check (dir->watch))
+  gboolean result = FALSE;
+  GFile *parent;
+
+  if (g_file_equal (directory, top_dir))
+    return TRUE;
+
+  parent = g_file_get_parent (directory);
+
+  if (dir_exists (parent, top_dir))
     {
-      if (dir_watch_is_valid (dir->watch))
-        trash_dir_enumerate (dir);
-      else
-        trash_dir_empty (dir);
+      struct stat buf;
+      gchar *path;
+
+      path = g_file_get_path (directory);
+      result = !lstat (path, &buf) && S_ISDIR (buf.st_mode);
+
+      g_free (path);
     }
+
+  g_object_unref (parent);
+
+  return result;
+}
+
+void
+trash_dir_rescan (TrashDir *dir)
+{
+  if (dir->watch)
+    dir_watch_check (dir->watch);
+
+  else if (dir_exists (dir->directory, dir->topdir))
+    trash_dir_enumerate (dir);
+
+  else
+    trash_dir_empty (dir);
 }
 
 static trash_dir_ui_hook ui_hook;
@@ -285,9 +337,15 @@
   dir->monitor = NULL;
   dir->is_homedir = is_homedir;
 
-  dir->watch = dir_watch_new (dir->directory, dir->topdir, watching,
-                              trash_dir_created, trash_dir_destroyed,
-                              dir);
+  if (watching)
+    dir->watch = dir_watch_new (dir->directory,
+                                dir->topdir,
+                                trash_dir_created,
+                                trash_dir_check,
+                                trash_dir_destroyed,
+                                dir);
+  else
+    dir->watch = NULL;
 
   if (ui_hook)
     ui_hook (dir, dir->directory);
@@ -306,7 +364,8 @@
 void
 trash_dir_free (TrashDir *dir)
 {
-  dir_watch_free (dir->watch);
+  if (dir->watch)
+    dir_watch_free (dir->watch);
 
   if (dir->monitor)
     g_object_unref (dir->monitor);

Modified: trunk/daemon/trashlib/trashitem.c
==============================================================================
--- trunk/daemon/trashlib/trashitem.c	(original)
+++ trunk/daemon/trashlib/trashitem.c	Fri Feb 27 23:04:31 2009
@@ -180,6 +180,7 @@
 
           rootdir = g_file_get_parent (trashdir);
           *original = g_file_get_child (rootdir, orig);
+          g_object_unref (rootdir);
         }
 
       g_free (orig);



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