summaryrefslogtreecommitdiff
path: root/daemon/gvfsbackendgoogle.c
diff options
context:
space:
mode:
authorOndrej Holy <oholy@redhat.com>2018-08-16 15:00:52 +0200
committerOndrej Holy <oholy@redhat.com>2018-09-21 11:30:17 +0000
commit649254c9fbf329af1e6f3b8a65c19d6e85c2ba62 (patch)
tree30903286e1885d0689d24a64817271e9e6d6ae13 /daemon/gvfsbackendgoogle.c
parent6e6d30d7d4456ccaaae1ccc2c6b5d2d942f21ba4 (diff)
downloadgvfs-649254c9fbf329af1e6f3b8a65c19d6e85c2ba62.tar.gz
google: Use cache for enumeration also
The reworked cache hasn't been used for enumeration results and also for missing files checks, which always caused rebuilding cache. Let's save timestamps also for enumerations and use it to prevent redundant cache rebuilds.
Diffstat (limited to 'daemon/gvfsbackendgoogle.c')
-rw-r--r--daemon/gvfsbackendgoogle.c62
1 files changed, 46 insertions, 16 deletions
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c
index e3a579c4..142acd5e 100644
--- a/daemon/gvfsbackendgoogle.c
+++ b/daemon/gvfsbackendgoogle.c
@@ -57,6 +57,7 @@ struct _GVfsBackendGoogle
GDataEntry *root;
GHashTable *entries; /* gchar *entry_id -> GDataEntry */
GHashTable *dir_entries; /* DirEntriesKey -> GDataEntry */
+ GHashTable *dir_timestamps; /* gchar *entry_id -> gint64 *timestamp */
GHashTable *monitors;
GList *dir_collisions;
GRecMutex mutex; /* guards cache */
@@ -463,6 +464,8 @@ remove_entry_full (GVfsBackendGoogle *self,
{
gchar *parent_id = ll->data;
+ g_hash_table_remove (self->dir_timestamps, parent_id);
+
k = dir_entries_key_new (id, parent_id);
g_debug (" remove_entry: Removed (%s, %s) -> %p\n", id, parent_id, entry);
g_hash_table_remove (self->dir_entries, k);
@@ -519,6 +522,8 @@ remove_dir (GVfsBackendGoogle *self,
/* g_strdup() is necessary to prevent segfault because gdata_entry_get_id() calls g_free() */
parent_id = g_strdup (gdata_entry_get_id (parent));
+ g_hash_table_remove (self->dir_timestamps, parent_id);
+
g_hash_table_iter_init (&iter, self->entries);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &entry))
{
@@ -562,6 +567,18 @@ is_entry_valid (GDataEntry *entry)
return (g_get_real_time () - *timestamp < REBUILD_ENTRIES_TIMEOUT * G_USEC_PER_SEC);
}
+static gboolean
+is_dir_listing_valid (GVfsBackendGoogle *self, GDataEntry *parent)
+{
+ gint64 *timestamp;
+
+ timestamp = g_hash_table_lookup (self->dir_timestamps, gdata_entry_get_id (parent));
+ if (timestamp != NULL)
+ return (g_get_real_time () - *timestamp < REBUILD_ENTRIES_TIMEOUT * G_USEC_PER_SEC);
+
+ return FALSE;
+}
+
static void
rebuild_dir (GVfsBackendGoogle *self,
GDataEntry *parent,
@@ -572,9 +589,10 @@ rebuild_dir (GVfsBackendGoogle *self,
GDataDocumentsQuery *query = NULL;
gboolean succeeded_once = FALSE;
gchar *search;
- const gchar *parent_id;
+ gchar *parent_id;
- parent_id = gdata_entry_get_id (parent);
+ /* g_strdup() is necessary to prevent segfault because gdata_entry_get_id() calls g_free() */
+ parent_id = g_strdup (gdata_entry_get_id (parent));
search = g_strdup_printf ("'%s' in parents", parent_id);
query = gdata_documents_query_new_with_limits (search, 1, MAX_RESULTS);
@@ -599,8 +617,14 @@ rebuild_dir (GVfsBackendGoogle *self,
if (!succeeded_once)
{
+ gint64 *timestamp;
+
remove_dir (self, parent);
+ timestamp = g_new (gint64, 1);
+ *timestamp = g_get_real_time ();
+ g_hash_table_insert (self->dir_timestamps, g_strdup (parent_id), timestamp);
+
succeeded_once = TRUE;
}
@@ -621,6 +645,7 @@ rebuild_dir (GVfsBackendGoogle *self,
out:
g_clear_object (&feed);
g_clear_object (&query);
+ g_free (parent_id);
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -640,8 +665,8 @@ resolve_child (GVfsBackendGoogle *self,
parent_id = gdata_entry_get_id (parent);
k = dir_entries_key_new (basename, parent_id);
entry = g_hash_table_lookup (self->dir_entries, k);
- // TODO: Rebuild only if dir listing is not valid
- if (entry == NULL || !is_entry_valid (entry))
+ if ((entry == NULL && !is_dir_listing_valid (self, parent)) ||
+ (entry != NULL && !is_entry_valid (entry)))
{
rebuild_dir (self, parent, cancellable, &local_error);
if (local_error != NULL)
@@ -651,11 +676,12 @@ resolve_child (GVfsBackendGoogle *self,
}
entry = g_hash_table_lookup (self->dir_entries, k);
- if (entry == NULL)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
- goto out;
- }
+ }
+
+ if (entry == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory"));
+ goto out;
}
out:
@@ -1355,7 +1381,7 @@ g_vfs_backend_google_enumerate (GVfsBackend *_self,
GError *error;
GHashTableIter iter;
char *parent_path;
- char *id;
+ char *id = NULL;
g_rec_mutex_lock (&self->mutex);
g_debug ("+ enumerate: %s\n", filename);
@@ -1375,13 +1401,15 @@ g_vfs_backend_google_enumerate (GVfsBackend *_self,
goto out;
}
- // TODO: Rebuild only if dir listing is not valid
- rebuild_dir (self, entry, cancellable, &error);
- if (error != NULL)
+ if (!is_dir_listing_valid (self, entry))
{
- g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
- g_error_free (error);
- goto out;
+ rebuild_dir (self, entry, cancellable, &error);
+ if (error != NULL)
+ {
+ g_vfs_job_failed_from_error (G_VFS_JOB (job), error);
+ g_error_free (error);
+ goto out;
+ }
}
g_vfs_job_succeeded (G_VFS_JOB (job));
@@ -2757,6 +2785,7 @@ g_vfs_backend_google_dispose (GObject *_self)
g_clear_object (&self->client);
g_clear_pointer (&self->entries, g_hash_table_unref);
g_clear_pointer (&self->dir_entries, g_hash_table_unref);
+ g_clear_pointer (&self->dir_timestamps, g_hash_table_unref);
G_OBJECT_CLASS (g_vfs_backend_google_parent_class)->dispose (_self);
}
@@ -2815,6 +2844,7 @@ g_vfs_backend_google_init (GVfsBackendGoogle *self)
entries_in_folder_equal,
dir_entries_key_free,
g_object_unref);
+ self->dir_timestamps = 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);
}