summaryrefslogtreecommitdiff
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
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.
-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);
}