[gvfs/wip/rishi/goa: 7/7] Introduce dir_entries and fix a bug in copy



commit 8acc84a1a543d859ff9c96d42e67e657d7092547
Author: Debarshi Ray <debarshir gnome org>
Date:   Thu Aug 27 20:28:50 2015 +0200

    Introduce dir_entries and fix a bug in copy

 daemon/gvfsbackendgoogle.c |  173 ++++++++++++++++++++++++++++++++++++--------
 1 files changed, 141 insertions(+), 32 deletions(-)
---
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c
index a5ca53e..d8cbf47 100644
--- a/daemon/gvfsbackendgoogle.c
+++ b/daemon/gvfsbackendgoogle.c
@@ -55,6 +55,7 @@ struct _GVfsBackendGoogle
   GDataDocumentsService *service;
   GDataEntry *root;
   GHashTable *entries;
+  GHashTable *dir_entries;
   GHashTable *lookaside;
   GHashTable *monitors;
   GRecMutex mutex;
@@ -86,6 +87,65 @@ G_DEFINE_TYPE(GVfsBackendGoogle, g_vfs_backend_google, G_VFS_TYPE_BACKEND)
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+typedef struct
+{
+  gchar *title_or_id;
+  gchar *parent_id;
+} DirEntriesKey;
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+DirEntriesKey *
+dir_entries_key_new (const gchar *title_or_id, const gchar *parent_id)
+{
+  DirEntriesKey *k;
+
+  k = g_slice_new (DirEntriesKey);
+  k->title_or_id = g_strdup (title_or_id);
+  k->parent_id = g_strdup (parent_id);
+  return k;
+}
+
+static void
+dir_entries_key_free (gpointer data)
+{
+  DirEntriesKey *k = (DirEntriesKey *) data;
+
+  if (k == NULL)
+    return;
+
+  g_free (k->title_or_id);
+  g_free (k->parent_id);
+  g_slice_free (DirEntriesKey, k);
+}
+
+guint
+entries_in_folder_hash (gconstpointer key)
+{
+  DirEntriesKey *k = (DirEntriesKey *) key;
+  guint hash1;
+  guint hash2;
+
+  hash1 = g_str_hash (k->title_or_id);
+  hash2 = g_str_hash (k->parent_id);
+  return hash1 ^ hash2;
+}
+
+gboolean
+entries_in_folder_equal (gconstpointer a, gconstpointer b)
+{
+  DirEntriesKey *k_a = (DirEntriesKey *) a;
+  DirEntriesKey *k_b = (DirEntriesKey *) b;
+
+  if (g_strcmp0 (k_a->title_or_id, k_b->title_or_id) == 0 &&
+      g_strcmp0 (k_a->parent_id, k_b->parent_id) == 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 static void
 insert_lookaside (GVfsBackendGoogle *self,
                   const gchar       *parent_id,
@@ -745,6 +805,60 @@ get_parent_basename (const gchar *filename)
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+insert_entry (GVfsBackendGoogle *self,
+              GDataEntry        *entry)
+{
+  DirEntriesKey *k;
+  const gchar *id;
+  const gchar *title;
+  gchar *parent_id;
+
+  id = gdata_entry_get_id (entry);
+  g_hash_table_insert (self->entries, g_strdup (id), g_object_ref (entry));
+
+  parent_id = get_parent_id (entry);
+  if (parent_id == NULL)
+    return;
+
+  k = dir_entries_key_new (id, parent_id);
+  g_hash_table_insert (self->dir_entries, k, g_object_ref (entry));
+
+  title = gdata_entry_get_title (entry);
+  k = dir_entries_key_new (title, parent_id);
+  g_hash_table_insert (self->dir_entries, k, g_object_ref (entry));
+
+  g_free (parent_id);
+}
+
+static void
+remove_entry (GVfsBackendGoogle *self,
+              GDataEntry        *entry)
+{
+  DirEntriesKey *k;
+  const gchar *id;
+  const gchar *title;
+  gchar *parent_id;
+
+  id = gdata_entry_get_id (entry);
+  g_hash_table_remove (self->entries, id);
+
+  parent_id = get_parent_id (entry);
+  if (parent_id == NULL)
+    return;
+
+  k = dir_entries_key_new (id, parent_id);
+  g_hash_table_remove (self->dir_entries, k);
+  dir_entries_key_free (k);
+
+  title = gdata_entry_get_title (entry);
+  k = dir_entries_key_new (title, parent_id);
+  g_hash_table_remove (self->dir_entries, k);
+  dir_entries_key_free (k);
+
+  g_free (parent_id);
+}
+
+static void
 rebuild_entries (GVfsBackendGoogle  *self,
                  GCancellable       *cancellable,
                  GError            **error)
@@ -782,6 +896,7 @@ rebuild_entries (GVfsBackendGoogle  *self,
       if (!succeeded_once)
         {
           g_hash_table_remove_all (self->entries);
+          g_hash_table_remove_all (self->dir_entries);
           succeeded_once = TRUE;
         }
 
@@ -792,10 +907,7 @@ rebuild_entries (GVfsBackendGoogle  *self,
       for (l = entries; l != NULL; l = l->next)
         {
           GDataEntry *entry = GDATA_ENTRY (l->data);
-          const gchar *id;
-
-          id = gdata_entry_get_id (entry);
-          g_hash_table_insert (self->entries, g_strdup (id), g_object_ref (entry));
+          insert_entry (self, entry);
         }
 
       gdata_query_next_page (GDATA_QUERY (query));
@@ -834,7 +946,6 @@ create_document (GVfsBackendGoogle  *self,
   GDataDocumentsFolder *parent;
   GError *local_error;
   gboolean is_root;
-  const gchar *id;
   gchar *parent_id = NULL;
   gchar *parent_path = NULL;
   gchar *path = NULL;
@@ -881,8 +992,7 @@ create_document (GVfsBackendGoogle  *self,
   if (local_error != NULL)
     goto out;
 
-  id = gdata_entry_get_id (GDATA_ENTRY (new_document));
-  g_hash_table_insert (self->entries, g_strdup (id), g_object_ref (new_document));
+  insert_entry (self, GDATA_ENTRY (new_document));
 
   path = get_entry_path (self, GDATA_ENTRY (new_document));
   if (path != NULL)
@@ -924,9 +1034,8 @@ g_vfs_backend_google_copy (GVfsBackend           *_self,
   GDataEntry *source_entry;
   GError *error;
   gboolean is_folder;
-  gboolean is_root;
+  gboolean destination_is_root;
   gboolean is_volatile_source;
-  const gchar *id;
   const gchar *real_destination_parent_path;
   const gchar *real_parent_path;
   const gchar *real_source;
@@ -996,8 +1105,8 @@ g_vfs_backend_google_copy (GVfsBackend           *_self,
       destination_parent_path = g_strdup (real_destination_parent_path);
     }
 
-  is_folder_or_root (destination_parent_path, NULL, NULL, &is_root);
-  if (is_root)
+  is_folder_or_root (destination_parent_path, NULL, NULL, &destination_is_root);
+  if (destination_is_root)
     {
       destination_parent = GDATA_DOCUMENTS_FOLDER (self->root);
     }
@@ -1020,6 +1129,16 @@ g_vfs_backend_google_copy (GVfsBackend           *_self,
     }
 
   source_entry = g_hash_table_lookup (self->entries, source_id);
+
+  if (!destination_is_root && destination_parent == NULL)
+    destination_parent = g_hash_table_lookup (self->entries, destination_parent_id);
+
+  if (source_entry == NULL || destination_parent == NULL)
+    {
+      g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
+      goto out;
+    }
+
   is_folder_or_root (source, source_entry, &is_folder, NULL);
   if (is_folder)
     {
@@ -1030,13 +1149,6 @@ g_vfs_backend_google_copy (GVfsBackend           *_self,
       goto out;
     }
 
-  destination_parent = g_hash_table_lookup (self->entries, destination_parent_id);
-  if (source_entry == NULL || destination_parent == NULL)
-    {
-      g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
-      goto out;
-    }
-
   error = NULL;
   new_entry = gdata_documents_service_add_entry_to_folder (self->service,
                                                            GDATA_DOCUMENTS_ENTRY (source_entry),
@@ -1050,8 +1162,7 @@ g_vfs_backend_google_copy (GVfsBackend           *_self,
       goto out;
     }
 
-  id = gdata_entry_get_id (GDATA_ENTRY (new_entry));
-  g_hash_table_insert (self->entries, g_strdup (id), g_object_ref (new_entry));
+  insert_entry (self, GDATA_ENTRY (new_entry));
 
   path = get_entry_path (self, GDATA_ENTRY (new_entry));
   if (path != NULL)
@@ -1248,7 +1359,7 @@ g_vfs_backend_google_delete (GVfsBackend   *_self,
       goto out;
     }
 
-  g_hash_table_remove (self->entries, id);
+  remove_entry (self, entry);
   if (path != NULL)
     g_hash_table_foreach (self->monitors, emit_delete_event, (gpointer) path);
 
@@ -1384,7 +1495,6 @@ g_vfs_backend_google_make_directory (GVfsBackend          *_self,
   gboolean is_display_name;
   gboolean is_root;
   gboolean needs_rebuild = FALSE;
-  const gchar *id;
   const gchar *real_parent_path;
   gchar *parent_id = NULL;
   gchar *parent_path = NULL;
@@ -1489,8 +1599,7 @@ g_vfs_backend_google_make_directory (GVfsBackend          *_self,
       goto out;
     }
 
-  id = gdata_entry_get_id (GDATA_ENTRY (new_entry));
-  g_hash_table_insert (self->entries, g_strdup (id), g_object_ref (new_entry));
+  insert_entry (self, GDATA_ENTRY (new_entry));
 
   path = get_entry_path (self, GDATA_ENTRY (new_entry));
   if (path != NULL)
@@ -1672,7 +1781,6 @@ g_vfs_backend_google_push (GVfsBackend           *_self,
   gboolean is_root;
   gboolean needs_overwrite = FALSE;
   const gchar *content_type;
-  const gchar *id;
   const gchar *title;
   gchar *basename = NULL;
   gchar *parent_id = NULL;
@@ -1899,8 +2007,7 @@ g_vfs_backend_google_push (GVfsBackend           *_self,
       goto out;
     }
 
-  id = gdata_entry_get_id (GDATA_ENTRY (new_document));
-  g_hash_table_insert (self->entries, g_strdup (id), g_object_ref (new_document));
+  insert_entry (self, GDATA_ENTRY (new_document));
 
   path = get_entry_path (self, GDATA_ENTRY (new_document));
   if (path != NULL)
@@ -2404,7 +2511,6 @@ g_vfs_backend_google_set_display_name (GVfsBackend           *_self,
   GError *error;
   gboolean is_root;
   gboolean is_volatile;
-  const gchar *new_id;
   gchar *escaped_filename = NULL;
   gchar *id = NULL;
   gchar *unescaped_filename = NULL;
@@ -2472,10 +2578,8 @@ g_vfs_backend_google_set_display_name (GVfsBackend           *_self,
       goto out;
     }
 
-  g_hash_table_remove (self->entries, id);
-
-  new_id = gdata_entry_get_id (new_entry);
-  g_hash_table_insert (self->entries, g_strdup (new_id), g_object_ref (new_entry));
+  remove_entry (self, entry);
+  insert_entry (self, new_entry);
 
   g_hash_table_foreach (self->monitors, emit_attribute_changed_event, (gpointer) filename);
 
@@ -2826,6 +2930,7 @@ g_vfs_backend_google_dispose (GObject *_self)
   g_clear_object (&self->root);
   g_clear_object (&self->client);
   g_clear_pointer (&self->entries, (GDestroyNotify) g_hash_table_unref);
+  g_clear_pointer (&self->dir_entries, (GDestroyNotify) g_hash_table_unref);
 
   G_OBJECT_CLASS (g_vfs_backend_google_parent_class)->dispose (_self);
 }
@@ -2884,6 +2989,10 @@ g_vfs_backend_google_init (GVfsBackendGoogle *self)
   g_vfs_backend_set_prefered_filename_encoding (G_VFS_BACKEND (self), "google-drive");
 
   self->entries = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+  self->dir_entries = g_hash_table_new_full (entries_in_folder_hash,
+                                             entries_in_folder_equal,
+                                             dir_entries_key_free,
+                                             g_object_unref);
   self->lookaside = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
   self->monitors = g_hash_table_new (NULL, NULL);
   g_rec_mutex_init (&self->mutex);


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