diff options
author | Ondrej Holy <oholy@redhat.com> | 2018-08-16 15:00:52 +0200 |
---|---|---|
committer | Ondrej Holy <oholy@redhat.com> | 2018-09-21 11:30:17 +0000 |
commit | 649254c9fbf329af1e6f3b8a65c19d6e85c2ba62 (patch) | |
tree | 30903286e1885d0689d24a64817271e9e6d6ae13 /daemon/gvfsbackendgoogle.c | |
parent | 6e6d30d7d4456ccaaae1ccc2c6b5d2d942f21ba4 (diff) | |
download | gvfs-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.c | 62 |
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); } |