changeset 1923:751d39d7ac30

added long-term cache for keywords
author Vladimir Nadvornik <nadvornik@suse.cz>
date Thu, 29 Sep 2011 12:36:08 +0200
parents 4f200abfccd7
children b0d53312dba7
files src/filedata.c src/metadata.c src/metadata.h src/typedefs.h
diffstat 4 files changed, 147 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/filedata.c	Tue Sep 27 22:06:09 2011 +0200
+++ b/src/filedata.c	Thu Sep 29 12:36:08 2011 +0200
@@ -664,6 +664,7 @@
 	g_assert(fd->magick == 0x12345678);
 	g_assert(fd->ref == 0);
 
+	metadata_cache_free(fd);
 	g_hash_table_remove(file_data_pool, fd->original_path);
 
 	g_free(fd->path);
--- a/src/metadata.c	Tue Sep 27 22:06:09 2011 +0200
+++ b/src/metadata.c	Thu Sep 29 12:36:08 2011 +0200
@@ -62,6 +62,113 @@
 static gboolean metadata_file_read(gchar *path, GList **keywords, gchar **comment);
 
 
+/*
+ *-------------------------------------------------------------------
+ * long-term cache - keep keywords from whole dir in memory
+ *-------------------------------------------------------------------
+ */
+
+/* fd->cached metadata list of lists
+   each particular list contains key as a first entry, then the values
+*/
+
+static void metadata_cache_update(FileData *fd, const gchar *key, const GList *values)
+{
+	GList *work;
+	
+	work = fd->cached_metadata;
+	while (work)
+		{
+		GList *entry = work->data;
+		gchar *entry_key = entry->data;
+		
+		if (strcmp(entry_key, key) == 0) 
+			{
+			/* key found - just replace values */
+			GList *old_values = entry->next;
+			entry->next = NULL;
+			old_values->prev = NULL;
+			string_list_free(old_values);
+			work->data = g_list_append(entry, string_list_copy(values));
+			DEBUG_1("updated %s %s\n", key, fd->path);
+			return;
+			}
+		work = work->next;
+		}
+	
+	/* key not found - prepend new entry */
+	fd->cached_metadata = g_list_prepend(fd->cached_metadata, 
+				g_list_prepend(string_list_copy(values), g_strdup(key)));
+	DEBUG_1("added %s %s\n", key, fd->path);
+
+}
+
+static const GList *metadata_cache_get(FileData *fd, const gchar *key)
+{
+	GList *work;
+	
+	work = fd->cached_metadata;
+	while (work)
+		{
+		GList *entry = work->data;
+		gchar *entry_key = entry->data;
+		
+		if (strcmp(entry_key, key) == 0) 
+			{
+			/* key found */
+			DEBUG_1("found %s %s\n", key, fd->path);
+			return entry;
+			}
+		work = work->next;
+		}
+	return NULL;
+	DEBUG_1("not found %s %s\n", key, fd->path);
+}
+
+static void metadata_cache_remove(FileData *fd, const gchar *key)
+{
+	GList *work;
+	
+	work = fd->cached_metadata;
+	while (work)
+		{
+		GList *entry = work->data;
+		gchar *entry_key = entry->data;
+		
+		if (strcmp(entry_key, key) == 0) 
+			{
+			/* key found */
+			string_list_free(entry);
+			fd->cached_metadata = g_list_delete_link(fd->cached_metadata, work);
+			DEBUG_1("removed %s %s\n", key, fd->path);
+			return;
+			}
+		work = work->next;
+		}
+	DEBUG_1("not removed %s %s\n", key, fd->path);
+}
+
+void metadata_cache_free(FileData *fd)
+{
+	GList *work;
+	if (fd->cached_metadata) DEBUG_1("freed %s\n", fd->path);
+	
+	work = fd->cached_metadata;
+	while (work)
+		{
+		GList *entry = work->data;
+		string_list_free(entry);
+		
+		work = work->next;
+		}
+	g_list_free(fd->cached_metadata);
+	fd->cached_metadata = NULL;
+}
+
+
+
+
+
 
 /*
  *-------------------------------------------------------------------
@@ -128,13 +235,18 @@
 
 void metadata_notify_cb(FileData *fd, NotifyType type, gpointer data)
 {
-	if ((type & (NOTIFY_REREAD | NOTIFY_CHANGE)) && g_list_find(metadata_write_queue, fd)) 
+	if (type & (NOTIFY_REREAD | NOTIFY_CHANGE))
 		{
-		DEBUG_1("Notify metadata: %s %04x", fd->path, type);
-		if (!isname(fd->path))
+		metadata_cache_free(fd);
+		
+		if (g_list_find(metadata_write_queue, fd)) 
 			{
-			/* ignore deleted files */
-			metadata_write_queue_remove(fd);
+			DEBUG_1("Notify metadata: %s %04x", fd->path, type);
+			if (!isname(fd->path))
+				{
+				/* ignore deleted files */
+				metadata_write_queue_remove(fd);
+				}
 			}
 		}
 }
@@ -255,6 +367,9 @@
 		fd->modified_xmp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)string_list_free);
 		}
 	g_hash_table_insert(fd->modified_xmp, g_strdup(key), string_list_copy((GList *)values));
+	
+	metadata_cache_remove(fd, key);
+	
 	if (fd->exif)
 		{
 		exif_update_metadata(fd->exif, key, values);
@@ -540,6 +655,7 @@
 {
 	ExifData *exif;
 	GList *list = NULL;
+	const GList *cache_entry;
 	if (!fd) return NULL;
 
 	/* unwritten data overide everything */
@@ -549,6 +665,13 @@
 		if (list) return string_list_copy(list);
 		}
 
+
+	if (format == METADATA_PLAIN && strcmp(key, KEYWORD_KEY) == 0 
+	    && (cache_entry = metadata_cache_get(fd, key)))
+		{
+		return string_list_copy(cache_entry->next);
+		}
+
 	/* 
 	    Legacy metadata file is the primary source if it exists.
 	    Merging the lists does not make much sense, because the existence of
@@ -558,8 +681,15 @@
 	*/
 	if (strcmp(key, KEYWORD_KEY) == 0)
 		{
-	        if (metadata_legacy_read(fd, &list, NULL)) return list;
-	        }
+		if (metadata_legacy_read(fd, &list, NULL)) 
+			{
+			if (format == METADATA_PLAIN) 
+				{
+				metadata_cache_update(fd, key, list);
+				}
+			return list;
+			}
+		}
 	else if (strcmp(key, COMMENT_KEY) == 0)
 		{
 		gchar *comment = NULL;
@@ -574,6 +704,12 @@
 	if (!exif) return NULL;
 	list = exif_get_metadata(exif, key, format);
 	exif_free_fd(fd, exif);
+	
+	if (format == METADATA_PLAIN && strcmp(key, KEYWORD_KEY) == 0)
+		{
+		metadata_cache_update(fd, key, list);
+		}
+		
 	return list;
 }
 
--- a/src/metadata.h	Tue Sep 27 22:06:09 2011 +0200
+++ b/src/metadata.h	Thu Sep 29 12:36:08 2011 +0200
@@ -18,6 +18,8 @@
 #define KEYWORD_KEY "Xmp.dc.subject"
 #define ORIENTATION_KEY "Xmp.tiff.Orientation"
 
+void metadata_cache_free(FileData *fd);
+
 gboolean metadata_write_queue_remove(FileData *fd);
 gboolean metadata_write_queue_remove_list(GList *list);
 gboolean metadata_write_perform(FileData *fd);
--- a/src/typedefs.h	Tue Sep 27 22:06:09 2011 +0200
+++ b/src/typedefs.h	Thu Sep 29 12:36:08 2011 +0200
@@ -521,6 +521,7 @@
 	
 	ExifData *exif;
 	GHashTable *modified_xmp; // hash table which contains unwritten xmp metadata in format: key->list of string values
+	GList *cached_metadata;
 };
 
 struct _LayoutOptions