[Xfce4-commits] <thunar:master> Directly collect the full info namespace for ls dir.

Nick Schermer noreply at xfce.org
Sat Nov 10 17:04:05 CET 2012


Updating branch refs/heads/master
         to 4d0efd73cd1f3d241fa2b9eb6c9fd2be2acaf8b4 (commit)
       from 4569ffdb7e8bb441c9485db58aece581444487be (commit)

commit 4d0efd73cd1f3d241fa2b9eb6c9fd2be2acaf8b4
Author: Nick Schermer <nick at xfce.org>
Date:   Sat Nov 10 15:42:53 2012 +0100

    Directly collect the full info namespace for ls dir.
    
    Adapt thunar_io_scan_directory to optionally return
    ThunarFile's instea of GFile and create ThunarFiles
    later for some io jobs.
    
    This trick is that we can directly use the enumerator
    to scan all the directory info and use that for the
    new ThunarFiles, this saves querying a file twice
    resulting in much faster directory loading.

 thunar/thunar-file.c              |  131 ++++++++++++++++++++++++++++---------
 thunar/thunar-file.h              |   11 ++-
 thunar/thunar-io-jobs.c           |   28 ++------
 thunar/thunar-io-scan-directory.c |   77 ++++++++++++++++------
 thunar/thunar-io-scan-directory.h |    1 +
 thunar/thunar-misc-jobs.c         |   21 +-----
 thunar/thunar-transfer-job.c      |    2 +-
 7 files changed, 176 insertions(+), 95 deletions(-)

diff --git a/thunar/thunar-file.c b/thunar/thunar-file.c
index 4a4f853..a99e7bb 100644
--- a/thunar/thunar-file.c
+++ b/thunar/thunar-file.c
@@ -1005,6 +1005,7 @@ thunar_file_load (ThunarFile   *file,
   _thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
   _thunar_return_val_if_fail (error == NULL || *error == NULL, FALSE);
   _thunar_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE);
+  _thunar_return_val_if_fail (G_IS_FILE (file->gfile), FALSE);
 
   /* reset the file */
   thunar_file_info_clear (file);
@@ -1100,51 +1101,77 @@ thunar_file_get (GFile   *gfile,
 }
 
 
-
 /**
- * thunar_file_get_async:
+ * thunar_file_get_with_info:
+ * @uri         : an URI or an absolute filename.
+ * @info        : #GFileInfo to use when loading the info.
+ * @not_mounted : if the file is mounted.
+ *
+ * Looks up the #ThunarFile referred to by @file. This function may return a
+ * ThunarFile even though the file doesn't actually exist. This is the case
+ * with remote URIs (like SFTP) for instance, if they are not mounted.
+ *
+ * This function does not use g_file_query_info() to get the info,
+ * but takes a reference on the @info,
+ *
+ * The caller is responsible to call g_object_unref()
+ * when done with the returned object.
+ *
+ * Return value: the #ThunarFile for @file or %NULL on errors.
  **/
-void
-thunar_file_get_async (GFile            *location,
-                       GCancellable     *cancellable,
-                       ThunarFileGetFunc func,
-                       gpointer          user_data)
+ThunarFile *
+thunar_file_get_with_info (GFile     *gfile,
+                           GFileInfo *info,
+                           gboolean   not_mounted)
 {
-  ThunarFile        *file;
-  ThunarFileGetData *data;
+  ThunarFile *file;
+
+  _thunar_return_val_if_fail (G_IS_FILE (gfile), NULL);
+  _thunar_return_val_if_fail (G_IS_FILE_INFO (info), NULL);
 
-  _thunar_return_if_fail (G_IS_FILE (location));
-  _thunar_return_if_fail (func != NULL);
-  
   /* check if we already have a cached version of that file */
-  file = thunar_file_cache_lookup (location);
+  file = thunar_file_cache_lookup (gfile);
   if (G_UNLIKELY (file != NULL))
     {
-      /* call the return function with the file from the cache */
-      (func) (location, file, NULL, user_data);
+      /* take a reference for the caller */
+      g_object_ref (file);
     }
   else
     {
-      /* allocate get data */
-      data = g_slice_new0 (ThunarFileGetData);
-      data->user_data = user_data;
-      data->func = func;
-      if (cancellable != NULL)
-        data->cancellable = g_object_ref (cancellable);
+      /* allocate a new object */
+      file = g_object_new (THUNAR_TYPE_FILE, NULL);
+      file->gfile = g_object_ref (gfile);
 
-      /* load the file information asynchronously */
-      g_file_query_info_async (location,
-                               THUNARX_FILE_INFO_NAMESPACE,
-                               G_FILE_QUERY_INFO_NONE,
-                               G_PRIORITY_DEFAULT,
-                               cancellable,
-                               thunar_file_get_async_finish,
-                               data);
+      /* reset the file */
+      thunar_file_info_clear (file);
+
+      /* set the passed info */
+      file->info = g_object_ref (info);
+
+      /* update the file from the information */
+      thunar_file_info_reload (file, NULL);
+
+      /* update the mounted info */
+      if (not_mounted)
+        FLAG_UNSET (file, THUNAR_FILE_FLAG_IS_MOUNTED);
+
+      /* setup lock until the file is inserted */
+      G_LOCK (file_cache_mutex);
+
+      /* insert the file into the cache */
+      g_hash_table_insert (file_cache, g_object_ref (file->gfile), file);
+
+      /* done inserting in the cache */
+      G_UNLOCK (file_cache_mutex);
     }
+
+  return file;
 }
 
 
 
+
+
 /**
  * thunar_file_get_for_uri:
  * @uri   : an URI or an absolute filename.
@@ -1179,6 +1206,50 @@ thunar_file_get_for_uri (const gchar *uri,
 
 
 /**
+ * thunar_file_get_async:
+ **/
+void
+thunar_file_get_async (GFile            *location,
+                       GCancellable     *cancellable,
+                       ThunarFileGetFunc func,
+                       gpointer          user_data)
+{
+  ThunarFile        *file;
+  ThunarFileGetData *data;
+
+  _thunar_return_if_fail (G_IS_FILE (location));
+  _thunar_return_if_fail (func != NULL);
+
+  /* check if we already have a cached version of that file */
+  file = thunar_file_cache_lookup (location);
+  if (G_UNLIKELY (file != NULL))
+    {
+      /* call the return function with the file from the cache */
+      (func) (location, file, NULL, user_data);
+    }
+  else
+    {
+      /* allocate get data */
+      data = g_slice_new0 (ThunarFileGetData);
+      data->user_data = user_data;
+      data->func = func;
+      if (cancellable != NULL)
+        data->cancellable = g_object_ref (cancellable);
+
+      /* load the file information asynchronously */
+      g_file_query_info_async (location,
+                               THUNARX_FILE_INFO_NAMESPACE,
+                               G_FILE_QUERY_INFO_NONE,
+                               G_PRIORITY_DEFAULT,
+                               cancellable,
+                               thunar_file_get_async_finish,
+                               data);
+    }
+}
+
+
+
+/**
  * thunar_file_get_file:
  * @file : a #ThunarFile instance.
  *
@@ -3330,7 +3401,7 @@ thunar_file_get_icon_name (const ThunarFile   *file,
        * 'Thunar', 'xfmedia', etc.).
        */
       if (G_UNLIKELY (thunar_file_is_executable (file)))
-        {
+        {g_message("exect crap");
           icon_name = g_file_get_basename (file->gfile);
           if (G_LIKELY (!gtk_icon_theme_has_icon (icon_theme, icon_name)))
             {
diff --git a/thunar/thunar-file.h b/thunar/thunar-file.h
index 7d04b60..48b3770 100644
--- a/thunar/thunar-file.h
+++ b/thunar/thunar-file.h
@@ -118,12 +118,15 @@ GType             thunar_file_get_type             (void) G_GNUC_CONST;
 
 ThunarFile       *thunar_file_get                  (GFile                  *file,
                                                     GError                **error);
+ThunarFile       *thunar_file_get_with_info        (GFile                  *file,
+                                                    GFileInfo              *info,
+                                                    gboolean                not_mounted);
 ThunarFile       *thunar_file_get_for_uri          (const gchar            *uri,
                                                     GError                **error);
-void              thunar_file_get_async            (GFile                 *location,
-                                                    GCancellable          *cancellable,
-                                                    ThunarFileGetFunc      func,
-                                                    gpointer               user_data);
+void              thunar_file_get_async            (GFile                  *location,
+                                                    GCancellable           *cancellable,
+                                                    ThunarFileGetFunc       func,
+                                                    gpointer                user_data);
 
 GFile            *thunar_file_get_file             (const ThunarFile       *file) G_GNUC_PURE;
 
diff --git a/thunar/thunar-io-jobs.c b/thunar/thunar-io-jobs.c
index a4b106c..9d904f9 100644
--- a/thunar/thunar-io-jobs.c
+++ b/thunar/thunar-io-jobs.c
@@ -57,7 +57,7 @@ _tij_collect_nofollow (ThunarJob *job,
       /* try to scan the directory */
       child_file_list = thunar_io_scan_directory (job, lp->data, 
                                                   G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, 
-                                                  TRUE, unlinking, &err);
+                                                  TRUE, unlinking, FALSE, &err);
 
       /* prepend the new files to the existing list */
       file_list = thunar_g_file_list_prepend (file_list, lp->data);
@@ -1170,12 +1170,9 @@ _thunar_io_jobs_ls (ThunarJob  *job,
                     GArray     *param_values,
                     GError    **error)
 {
-  ThunarFile *file;
-  GError     *err = NULL;
-  GFile      *directory;
-  GList      *file_list = NULL;
-  GList      *lp;
-  GList      *path_list;
+  GError *err = NULL;
+  GFile  *directory;
+  GList  *file_list = NULL;
 
   _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
   _thunar_return_val_if_fail (param_values != NULL, FALSE);
@@ -1192,22 +1189,9 @@ _thunar_io_jobs_ls (ThunarJob  *job,
   _thunar_assert (G_IS_FILE (directory));
 
   /* collect directory contents (non-recursively) */
-  path_list = thunar_io_scan_directory (job, directory, 
+  file_list = thunar_io_scan_directory (job, directory,
                                         G_FILE_QUERY_INFO_NONE, 
-                                        FALSE, FALSE, &err);
-
-  /* turn the GFile list into a ThunarFile list */
-  for (lp = g_list_last (path_list); 
-       err == NULL && !exo_job_is_cancelled (EXO_JOB (job)) && lp != NULL; 
-       lp = lp->prev)
-    {
-      file = thunar_file_get (lp->data, &err);
-      if (G_LIKELY (file != NULL))
-        file_list = g_list_prepend (file_list, file);
-    }
-
-  /* free the GFile list */
-  thunar_g_file_list_free (path_list);
+                                        FALSE, FALSE, TRUE, &err);
 
   /* abort on errors or cancellation */
   if (err != NULL)
diff --git a/thunar/thunar-io-scan-directory.c b/thunar/thunar-io-scan-directory.c
index 6c38733..66ddbdf 100644
--- a/thunar/thunar-io-scan-directory.c
+++ b/thunar/thunar-io-scan-directory.c
@@ -39,6 +39,7 @@ thunar_io_scan_directory (ThunarJob          *job,
                           GFileQueryInfoFlags flags,
                           gboolean            recursively,
                           gboolean            unlinking,
+                          gboolean            return_thunar_files,
                           GError            **error)
 {
   GFileEnumerator *enumerator;
@@ -48,6 +49,9 @@ thunar_io_scan_directory (ThunarJob          *job,
   GFile           *child_file;
   GList           *child_files = NULL;
   GList           *files = NULL;
+  const gchar     *namespace;
+  ThunarFile      *thunar_file;
+  gboolean         is_mounted;
   
   _thunar_return_val_if_fail (THUNAR_IS_JOB (job), NULL);
   _thunar_return_val_if_fail (G_IS_FILE (file), NULL);
@@ -80,10 +84,15 @@ thunar_io_scan_directory (ThunarJob          *job,
   if (type != G_FILE_TYPE_DIRECTORY)
     return NULL;
 
+  /* determine the namespace */
+  if (return_thunar_files)
+    namespace = THUNARX_FILE_INFO_NAMESPACE;
+  else
+    namespace = G_FILE_ATTRIBUTE_STANDARD_TYPE ","
+                G_FILE_ATTRIBUTE_STANDARD_NAME;
+
   /* try to read from the direectory */
-  enumerator = g_file_enumerate_children (file,
-                                          G_FILE_ATTRIBUTE_STANDARD_TYPE ","
-                                          G_FILE_ATTRIBUTE_STANDARD_NAME,
+  enumerator = g_file_enumerate_children (file, namespace,
                                           flags, exo_job_get_cancellable (EXO_JOB (job)),
                                           &err);
 
@@ -93,36 +102,64 @@ thunar_io_scan_directory (ThunarJob          *job,
       g_propagate_error (error, err);
       return NULL;
     }
-        
-  /* query info of the first child */
-  info = g_file_enumerator_next_file (enumerator,
-                                      exo_job_get_cancellable (EXO_JOB (job)), 
-                                      &err);
-
-  /* iterate over children one by one as long as there's no error */
-  while (info != NULL && err == NULL && !exo_job_is_cancelled (EXO_JOB (job)))
+
+  /* iterate over children one by one */
+  while (!exo_job_is_cancelled (EXO_JOB (job)))
     {
-      /* create GFile for the child and prepend it to the file list */
+      /* query info of the child */
+      info = g_file_enumerator_next_file (enumerator,
+                                          exo_job_get_cancellable (EXO_JOB (job)), 
+                                          &err);
+
+      if (G_UNLIKELY (info == NULL))
+        break;
+
+      is_mounted = TRUE;
+      if (err != NULL)
+        {
+          if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED))
+            {
+              is_mounted = FALSE;
+              g_clear_error (&err);
+            }
+          else
+            {
+              /* break on errors */
+              break;
+            }
+        }
+
+      /* create GFile for the child */
       child_file = g_file_get_child (file, g_file_info_get_name (info));
-      files = thunar_g_file_list_prepend (files, child_file);
+
+      if (return_thunar_files)
+        {
+          /* Prepend the ThunarFile */
+          thunar_file = thunar_file_get_with_info (child_file, info, !is_mounted);
+          files = thunar_g_file_list_prepend (files, thunar_file);
+          g_object_unref (G_OBJECT (thunar_file));
+        }
+      else
+        {
+          /* Prepend the GFile */
+          files = thunar_g_file_list_prepend (files, child_file);
+        }
 
       /* if the child is a directory and we need to recurse ... just do so */
-      if (recursively && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+      if (recursively
+          && is_mounted
+          && g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
         {
           child_files = thunar_io_scan_directory (job, child_file, flags, recursively, 
-                                                  unlinking, &err);
+                                                  unlinking, return_thunar_files, &err);
 
           /* prepend children to the file list to make sure they're 
            * processed first (required for unlinking) */
           files = g_list_concat (child_files, files);
         }
-      
+
       g_object_unref (child_file);
       g_object_unref (info);
-
-      info = g_file_enumerator_next_file (enumerator, 
-                                          exo_job_get_cancellable (EXO_JOB (job)), 
-                                          &err);
     }
 
   /* release the enumerator */
diff --git a/thunar/thunar-io-scan-directory.h b/thunar/thunar-io-scan-directory.h
index 1ace975..8137d6a 100644
--- a/thunar/thunar-io-scan-directory.h
+++ b/thunar/thunar-io-scan-directory.h
@@ -33,6 +33,7 @@ GList *thunar_io_scan_directory (ThunarJob          *job,
                                  GFileQueryInfoFlags flags,
                                  gboolean            recursively,
                                  gboolean            unlinking,
+                                 gboolean            return_thunar_files,
                                  GError            **error);
 
 G_END_DECLS
diff --git a/thunar/thunar-misc-jobs.c b/thunar/thunar-misc-jobs.c
index eddc2e1..373e2f5 100644
--- a/thunar/thunar-misc-jobs.c
+++ b/thunar/thunar-misc-jobs.c
@@ -37,13 +37,10 @@ _thunar_misc_jobs_load_templates (ThunarJob  *job,
                                   GArray     *param_values,
                                   GError    **error)
 {
-  ThunarFile  *file;
   GtkWidget   *menu;
   GFile       *home_dir;
   GFile       *templates_dir;
   GList       *files = NULL;
-  GList       *lp;
-  GList       *paths = NULL;
   const gchar *path;
 
   _thunar_return_val_if_fail (THUNAR_IS_JOB (job), FALSE);
@@ -62,22 +59,10 @@ _thunar_misc_jobs_load_templates (ThunarJob  *job,
 
   if (G_LIKELY (!g_file_equal (templates_dir, home_dir)))
     {
-      paths = thunar_io_scan_directory (job, templates_dir, 
+      /* load the ThunarFiles */
+      files = thunar_io_scan_directory (job, templates_dir,
                                         G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                                        TRUE, FALSE, NULL);
-
-      /* turn the GFile list into a ThunarFile list */
-      for (lp = g_list_last (paths); 
-           lp != NULL && !exo_job_is_cancelled (EXO_JOB (job));
-           lp = lp->prev)
-        {
-          file = thunar_file_get (lp->data, NULL);
-          if (G_LIKELY (file != NULL))
-            files = g_list_prepend (files, file);
-        }
-
-      /* free the GFile list */
-      thunar_g_file_list_free (paths);
+                                        TRUE, FALSE, TRUE, NULL);
     }
 
   g_object_unref (templates_dir);
diff --git a/thunar/thunar-transfer-job.c b/thunar/thunar-transfer-job.c
index 178a5bc..b33557c 100644
--- a/thunar/thunar-transfer-job.c
+++ b/thunar/thunar-transfer-job.c
@@ -222,7 +222,7 @@ thunar_transfer_job_collect_node (ThunarTransferJob  *job,
       /* scan the directory for immediate children */
       file_list = thunar_io_scan_directory (THUNAR_JOB (job), node->source_file,
                                             G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
-                                            FALSE, FALSE, &err);
+                                            FALSE, FALSE, FALSE, &err);
 
       /* add children to the transfer node */
       for (lp = file_list; err == NULL && lp != NULL; lp = lp->next)


More information about the Xfce4-commits mailing list