summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gio/glocalfileinfo.c76
1 files changed, 58 insertions, 18 deletions
diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c
index 90fcb3336..f1ee94682 100644
--- a/gio/glocalfileinfo.c
+++ b/gio/glocalfileinfo.c
@@ -1547,15 +1547,44 @@ win32_get_file_user_info (const gchar *filename,
/* support for '.hidden' files */
G_LOCK_DEFINE_STATIC (hidden_cache);
static GHashTable *hidden_cache;
+static GSource *hidden_cache_source = NULL; /* Under the hidden_cache lock */
+static guint hidden_cache_ttl = 5; /* In seconds */
+
+typedef struct
+{
+ GHashTable *hidden_files;
+ gint64 timestamp;
+} HiddenCacheData;
static gboolean
remove_from_hidden_cache (gpointer user_data)
{
+ HiddenCacheData *data;
+ GHashTableIter iter;
+ gboolean retval;
+ gint64 timestamp;
+
G_LOCK (hidden_cache);
- g_hash_table_remove (hidden_cache, user_data);
+ timestamp = g_source_get_time (hidden_cache_source) / G_USEC_PER_SEC;
+
+ g_hash_table_iter_init (&iter, hidden_cache);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &data))
+ {
+ if (timestamp > (data->timestamp / G_USEC_PER_SEC) + hidden_cache_ttl)
+ g_hash_table_iter_remove (&iter);
+ }
+
+ if (g_hash_table_size (hidden_cache) == 0)
+ {
+ g_clear_pointer (&hidden_cache_source, g_source_unref);
+ retval = G_SOURCE_REMOVE;
+ }
+ else
+ retval = G_SOURCE_CONTINUE;
+
G_UNLOCK (hidden_cache);
- return FALSE;
+ return retval;
}
static GHashTable *
@@ -1593,16 +1622,19 @@ read_hidden_file (const gchar *dirname)
}
static void
-maybe_unref_hash_table (gpointer data)
+free_hidden_file_data (gpointer user_data)
{
- if (data != NULL)
- g_hash_table_unref (data);
+ HiddenCacheData *data = user_data;
+
+ g_clear_pointer (&data->hidden_files, g_hash_table_unref);
+ g_free (data);
}
static gboolean
file_is_hidden (const gchar *path,
const gchar *basename)
{
+ HiddenCacheData *data;
gboolean result;
gchar *dirname;
gpointer table;
@@ -1613,28 +1645,36 @@ file_is_hidden (const gchar *path,
if G_UNLIKELY (hidden_cache == NULL)
hidden_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, maybe_unref_hash_table);
+ g_free, free_hidden_file_data);
if (!g_hash_table_lookup_extended (hidden_cache, dirname,
- NULL, &table))
+ NULL, (gpointer *) &data))
{
gchar *mydirname;
- GSource *remove_from_cache_source;
+
+ data = g_new0 (HiddenCacheData, 1);
+ data->hidden_files = table = read_hidden_file (dirname);
+ data->timestamp = g_get_monotonic_time ();
g_hash_table_insert (hidden_cache,
mydirname = g_strdup (dirname),
- table = read_hidden_file (dirname));
+ data);
- remove_from_cache_source = g_timeout_source_new_seconds (5);
- g_source_set_priority (remove_from_cache_source, G_PRIORITY_DEFAULT);
- g_source_set_callback (remove_from_cache_source,
- remove_from_hidden_cache,
- mydirname,
- NULL);
- g_source_attach (remove_from_cache_source,
- GLIB_PRIVATE_CALL (g_get_worker_context) ());
- g_source_unref (remove_from_cache_source);
+ if (!hidden_cache_source)
+ {
+ hidden_cache_source = g_timeout_source_new_seconds (7);
+ g_source_set_priority (hidden_cache_source, G_PRIORITY_DEFAULT);
+ g_source_set_name (hidden_cache_source,
+ "[gio] remove_from_hidden_cache");
+ g_source_set_callback (hidden_cache_source,
+ remove_from_hidden_cache,
+ NULL, NULL);
+ g_source_attach (hidden_cache_source,
+ GLIB_PRIVATE_CALL (g_get_worker_context) ());
+ }
}
+ else
+ table = data->hidden_files;
result = table != NULL && g_hash_table_contains (table, basename);