[gnome-builder/wip/libide: 45/237] vcs: add some safeguards to DirectoryVcs



commit 08d1b0e42a7b78f5f98675f2dd744eb9f16e4041
Author: Christian Hergert <christian hergert me>
Date:   Sat Feb 7 19:11:20 2015 -0800

    vcs: add some safeguards to DirectoryVcs
    
    Try to not load so many files with directory vcs. It's okay to "soft fail"
    after say 2000 files have been loaded. We want to be careful with the
    situation where we open files starting from the home directory (which
    shouldn't happen after we have project loading, but does now).
    
    Also, the directory loader needs to be rewritten to be synchronous and
    run from a GTaskThreadFunc.

 libide/directory/ide-directory-vcs.c   |   77 +++----------------------------
 libide/tasks/ide-load-directory-task.c |   27 +++++++++--
 libide/tasks/ide-load-directory-task.h |    1 +
 3 files changed, 32 insertions(+), 73 deletions(-)
---
diff --git a/libide/directory/ide-directory-vcs.c b/libide/directory/ide-directory-vcs.c
index 0df8992..9796d59 100644
--- a/libide/directory/ide-directory-vcs.c
+++ b/libide/directory/ide-directory-vcs.c
@@ -24,80 +24,23 @@
 #include "ide-project-files.h"
 #include "tasks/ide-load-directory-task.h"
 
-typedef struct
-{
-  gpointer dummy;
-} IdeDirectoryVcsPrivate;
+/*
+ * TODO: This all needs to be written synchronously on a thread so that we
+ *       cant hit the case of too many open files. Right now, child directories
+ *       are done async, and that can fail.
+ */
 
-enum
-{
-  PROP_0,
-  LAST_PROP
-};
+#define LOAD_MAX_FILES 2000
 
 static void async_initable_iface_init (GAsyncInitableIface *iface);
 
 G_DEFINE_TYPE_EXTENDED (IdeDirectoryVcs, ide_directory_vcs, IDE_TYPE_VCS, 0,
-                        G_ADD_PRIVATE (IdeDirectoryVcs)
                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE,
                                                async_initable_iface_init))
 
-#if 0
-static GParamSpec *gParamSpecs [LAST_PROP];
-#endif
-
-static void
-ide_directory_vcs_finalize (GObject *object)
-{
-#if 0
-  IdeDirectoryVcs *self = (IdeDirectoryVcs *)object;
-  IdeDirectoryVcsPrivate *priv = ide_directory_vcs_get_instance_private (self);
-#endif
-
-  G_OBJECT_CLASS (ide_directory_vcs_parent_class)->finalize (object);
-}
-
-static void
-ide_directory_vcs_get_property (GObject    *object,
-                                guint       prop_id,
-                                GValue     *value,
-                                GParamSpec *pspec)
-{
-#if 0
-  IdeDirectoryVcs *vcs = IDE_DIRECTORY_VCS (object);
-#endif
-
-  switch (prop_id) {
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-  }
-}
-
-static void
-ide_directory_vcs_set_property (GObject      *object,
-                                guint         prop_id,
-                                const GValue *value,
-                                GParamSpec   *pspec)
-{
-#if 0
-  IdeDirectoryVcs *vcs = IDE_DIRECTORY_VCS (object);
-#endif
-
-  switch (prop_id) {
-  default:
-    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-  }
-}
-
 static void
 ide_directory_vcs_class_init (IdeDirectoryVcsClass *klass)
 {
-  GObjectClass *object_class;
-
-  object_class = G_OBJECT_CLASS (klass);
-  object_class->finalize = ide_directory_vcs_finalize;
-  object_class->get_property = ide_directory_vcs_get_property;
-  object_class->set_property = ide_directory_vcs_set_property;
 }
 
 static void
@@ -134,12 +77,8 @@ ide_directory_vcs_init_async (GAsyncInitable      *initable,
                         NULL);
   ide_project_item_append (root, files);
 
-  task = ide_load_directory_task_new (self,
-                                      directory,
-                                      files,
-                                      io_priority,
-                                      cancellable,
-                                      callback,
+  task = ide_load_directory_task_new (self, directory, files, LOAD_MAX_FILES,
+                                      io_priority, cancellable, callback,
                                       user_data);
 
   g_object_unref (files);
diff --git a/libide/tasks/ide-load-directory-task.c b/libide/tasks/ide-load-directory-task.c
index 1cef4c8..33901df 100644
--- a/libide/tasks/ide-load-directory-task.c
+++ b/libide/tasks/ide-load-directory-task.c
@@ -22,7 +22,7 @@
 #include "ide-project-item.h"
 #include "ide-project-file.h"
 
-#define NUM_FILES_DEFAULT 1000
+#define NUM_FILES_DEFAULT 100
 
 typedef struct
 {
@@ -30,6 +30,8 @@ typedef struct
   guint       failed : 1;
   GTask      *task;
   GHashTable *project_items;
+  gsize       file_count;
+  gsize       max_files;
 } TaskState;
 
 static void enumerate_children_cb (GObject      *object,
@@ -49,6 +51,7 @@ task_state_unref (TaskState *state)
 
   if (--state->ref_count == 0)
     {
+      g_print ("Failed: %d\n", state->failed);
       if (state->failed)
         g_task_return_new_error (state->task,
                                  G_IO_ERROR,
@@ -74,7 +77,8 @@ task_state_ref (TaskState *state)
 static gboolean
 should_ignore_file (const gchar *name)
 {
-  g_return_val_if_fail (name, FALSE);
+  if (!name || !*name || (*name == '.'))
+    return TRUE;
 
   if (g_str_equal (name, ".git"))
     return TRUE;
@@ -102,7 +106,7 @@ next_files_cb (GObject      *object,
   TaskState *state = user_data;
   GError *error = NULL;
   GFile *directory;
-  GList *list;
+  GList *list = NULL;
   GList *iter;
 
   g_return_if_fail (G_IS_FILE_ENUMERATOR (enumerator));
@@ -116,6 +120,7 @@ next_files_cb (GObject      *object,
 
   if (error)
     {
+      g_warning ("%s\n", error->message);
       state->failed = TRUE;
       goto cleanup;
     }
@@ -136,11 +141,18 @@ next_files_cb (GObject      *object,
           (file_type != G_FILE_TYPE_REGULAR))
         continue;
 
-      name = g_file_info_get_display_name (file_info);
+      state->file_count++;
 
+      name = g_file_info_get_name (file_info);
+      g_print ("name: %s\n", name);
       if (should_ignore_file (name))
         continue;
 
+      name = g_file_info_get_display_name (file_info);
+
+      if (state->file_count >= state->max_files)
+        goto cleanup;
+
       item = g_object_new (IDE_TYPE_PROJECT_FILE,
                            "context", context,
                            "file-info", file_info,
@@ -157,6 +169,7 @@ next_files_cb (GObject      *object,
                                g_object_ref (item));
           g_file_enumerate_children_async (file,
                                            (G_FILE_ATTRIBUTE_STANDARD_TYPE","
+                                            G_FILE_ATTRIBUTE_STANDARD_NAME","
                                             G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME),
                                            G_FILE_QUERY_INFO_NONE,
                                            G_PRIORITY_DEFAULT,
@@ -192,6 +205,7 @@ enumerate_children_cb (GObject      *object,
 
   if (!enumerator)
     {
+      g_warning ("%s\n", error->message);
       state->failed = TRUE;
       goto cleanup;
     }
@@ -226,6 +240,7 @@ query_info_cb (GObject      *object,
 
   if (!file_info)
     {
+      g_warning ("%s\n", error->message);
       state->failed = TRUE;
       goto cleanup;
     }
@@ -234,6 +249,7 @@ query_info_cb (GObject      *object,
 
   if (file_type != G_FILE_TYPE_DIRECTORY)
     {
+      g_warning (_("Not a directory"));
       state->failed = TRUE;
       goto cleanup;
     }
@@ -256,6 +272,7 @@ GTask *
 ide_load_directory_task_new (gpointer             source_object,
                              GFile               *directory,
                              IdeProjectItem      *parent,
+                             gsize                max_files,
                              int                  io_priority,
                              GCancellable        *cancellable,
                              GAsyncReadyCallback  callback,
@@ -270,6 +287,8 @@ ide_load_directory_task_new (gpointer             source_object,
 
   state = g_slice_new0 (TaskState);
   state->ref_count = 1;
+  state->max_files = max_files;
+  state->file_count = 0;
   state->task = g_task_new (source_object, cancellable, callback, user_data);
   state->project_items = g_hash_table_new_full (g_direct_hash,
                                                 g_direct_equal,
diff --git a/libide/tasks/ide-load-directory-task.h b/libide/tasks/ide-load-directory-task.h
index c879b63..d15ecde 100644
--- a/libide/tasks/ide-load-directory-task.h
+++ b/libide/tasks/ide-load-directory-task.h
@@ -28,6 +28,7 @@ G_BEGIN_DECLS
 GTask *ide_load_directory_task_new (gpointer             source_object,
                                     GFile               *directory,
                                     IdeProjectItem      *parent,
+                                    gsize                max_files,
                                     int                  io_priority,
                                     GCancellable        *cancellable,
                                     GAsyncReadyCallback  callback,


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