diff -u -p -r1.16 rb-refstring.c
--- rhythmdb/rb-refstring.c	24 Jul 2006 01:34:08 -0000	1.16
+++ rhythmdb/rb-refstring.c	24 Jul 2006 09:25:37 -0000
@@ -84,6 +84,21 @@ rb_refstring_new (const char *init)
 	return ret;
 }
 
+RBRefString *
+rb_refstring_find (const char *init)
+{
+	RBRefString *ret;
+
+	g_mutex_lock (rb_refstrings_mutex);
+	ret = g_hash_table_lookup (rb_refstrings, init);
+
+	if (ret)
+		rb_refstring_ref (ret);
+
+	g_mutex_unlock (rb_refstrings_mutex);
+	return ret;
+}
+
 void
 rb_refstring_unref (RBRefString *val)
 {
diff -u -p -r1.8 rb-refstring.h
--- rhythmdb/rb-refstring.h	14 Jul 2006 12:29:27 -0000	1.8
+++ rhythmdb/rb-refstring.h	24 Jul 2006 09:25:37 -0000
@@ -30,6 +30,7 @@ void		rb_refstring_system_init (void);
 void		rb_refstring_system_shutdown (void);
 
 RBRefString *	rb_refstring_new (const char *init);
+RBRefString *	rb_refstring_find (const char *init);
 
 RBRefString *	rb_refstring_ref (RBRefString *val);
 void		rb_refstring_unref (RBRefString *val);
diff -u -p -r1.5 rhythmdb-monitor.c
--- rhythmdb/rhythmdb-monitor.c	14 Jul 2006 12:29:27 -0000	1.5
+++ rhythmdb/rhythmdb-monitor.c	24 Jul 2006 09:25:37 -0000
@@ -51,8 +51,8 @@ rhythmdb_init_monitoring (RhythmDB *db)
 								 (GDestroyNotify) g_free,
 								 NULL);
 
-	db->priv->changed_files = g_hash_table_new_full (g_str_hash, g_str_equal,
-							 (GDestroyNotify) g_free,
+	db->priv->changed_files = g_hash_table_new_full (rb_refstring_hash, rb_refstring_equal,
+							 (GDestroyNotify) rb_refstring_unref,
 							 NULL);
 
 	g_signal_connect (G_OBJECT (gnome_vfs_get_volume_monitor ()),
@@ -102,7 +102,10 @@ monitor_entry_file (RhythmDBEntry *entry
 	GError *error = NULL;
 
 	if (entry->type == RHYTHMDB_ENTRY_TYPE_SONG) {
-		rhythmdb_monitor_uri_path (db, entry->location, &error);
+		const char *loc;
+
+		loc = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+		rhythmdb_monitor_uri_path (db, loc, &error);
 	}
 
 	if (error) {
@@ -152,7 +155,7 @@ monitor_library_directory (const char *u
 }
 
 static gboolean
-rhythmdb_check_changed_file (const char *uri, gpointer data, RhythmDB *db)
+rhythmdb_check_changed_file (RBRefString *uri, gpointer data, RhythmDB *db)
 {
 	GTimeVal time;
 	glong time_sec = GPOINTER_TO_INT (data);
@@ -163,14 +166,14 @@ rhythmdb_check_changed_file (const char 
 		RhythmDBEvent *event = g_new0 (RhythmDBEvent, 1);
 		event->db = db;
 		event->type = RHYTHMDB_EVENT_FILE_CREATED_OR_MODIFIED;
-		event->uri = g_strdup (uri);
+		event->uri = rb_refstring_ref (uri);
 
 		g_async_queue_push (db->priv->event_queue, event);
-		rb_debug ("adding newly located file %s", uri);
+		rb_debug ("adding newly located file %s", rb_refstring_get (uri));
 		return TRUE;
 	}
 
-	rb_debug ("waiting to add newly located file %s", uri);
+	rb_debug ("waiting to add newly located file %s", rb_refstring_get (uri));
 
 	return FALSE;
 }
@@ -242,7 +245,7 @@ rhythmdb_directory_change_cb (GnomeVFSMo
 
 			g_get_current_time (&time);
 			g_hash_table_replace (db->priv->changed_files,
-					      g_strdup (info_uri),
+					      rb_refstring_new (info_uri),
 					      GINT_TO_POINTER (time.tv_sec));
 		}
 		break;
@@ -251,7 +254,7 @@ rhythmdb_directory_change_cb (GnomeVFSMo
 			RhythmDBEvent *event = g_new0 (RhythmDBEvent, 1);
 			event->db = db;
 			event->type = RHYTHMDB_EVENT_FILE_DELETED;
-			event->uri = g_strdup (info_uri);
+			event->uri = rb_refstring_new (info_uri);
 			g_async_queue_push (db->priv->event_queue, event);
 		}
 		break;
diff -u -p -r1.19 rhythmdb-private.h
--- rhythmdb/rhythmdb-private.h	23 Jul 2006 16:02:56 -0000	1.19
+++ rhythmdb/rhythmdb-private.h	24 Jul 2006 09:25:37 -0000
@@ -89,7 +89,7 @@ struct RhythmDBEntry_ {
 	GDate date;
 
 	/* filesystem */
-	char *location;
+	RBRefString *location;
 	RBRefString *mountpoint;
 	guint64 file_size;
 	RBRefString *mimetype;
@@ -108,7 +108,7 @@ struct RhythmDBEntry_ {
 	gpointer last_seen_str;
 
 	/* playback error string */
-	char *playback_error;
+	RBRefString *playback_error;
 };
 
 struct RhythmDBPrivate
@@ -188,8 +188,8 @@ typedef struct
 		RHYTHMDB_EVENT_FILE_DELETED,
 		RHYTHMDB_EVENT_ENTRY_SET
 	} type;
-	char *uri;
-	char *real_uri; /* Target of a symlink, if any */
+	RBRefString *uri;
+	RBRefString *real_uri; /* Target of a symlink, if any */
 	RhythmDBEntryType entry_type;
 
 	GError *error;
@@ -217,6 +217,7 @@ void rhythmdb_entry_set_internal (Rhythm
 				  gboolean notify_if_inserted, guint propid,
 				  const GValue *value);
 void rhythmdb_entry_type_foreach (RhythmDB *db, GHFunc func, gpointer data);
+RhythmDBEntry *	rhythmdb_entry_lookup_by_location_refstring (RhythmDB *db, RBRefString *uri);
 
 /* from rhythmdb-monitor.c */
 void rhythmdb_init_monitoring (RhythmDB *db);
diff -u -p -r1.115 rhythmdb-tree.c
--- rhythmdb/rhythmdb-tree.c	23 Jul 2006 16:02:56 -0000	1.115
+++ rhythmdb/rhythmdb-tree.c	24 Jul 2006 09:25:39 -0000
@@ -72,7 +72,7 @@ static gboolean rhythmdb_tree_entry_set 
 static void rhythmdb_tree_entry_delete (RhythmDB *db, RhythmDBEntry *entry);
 static void rhythmdb_tree_entry_delete_by_type (RhythmDB *adb, RhythmDBEntryType type);
 
-static RhythmDBEntry * rhythmdb_tree_entry_lookup_by_location (RhythmDB *db, const char *uri);
+static RhythmDBEntry * rhythmdb_tree_entry_lookup_by_location (RhythmDB *db, RBRefString *uri);
 static void rhythmdb_tree_entry_foreach (RhythmDB *adb, GFunc func, gpointer user_data);
 static void rhythmdb_tree_do_full_query (RhythmDB *db, GPtrArray *query,
 					 RhythmDBQueryResults *results,
@@ -127,13 +127,13 @@ struct RhythmDBTreePrivate
 
 typedef struct
 {
-	char *name;
-	char *value;
+	RBRefString *name;
+	RBRefString *value;
 } RhythmDBUnknownEntryProperty;
 
 typedef struct
 {
-	char *typename;
+	RBRefString *typename;
 	GList *properties;
 } RhythmDBUnknownEntry;
 
@@ -174,15 +174,15 @@ rhythmdb_tree_init (RhythmDBTree *db)
 {
 	db->priv = RHYTHMDB_TREE_GET_PRIVATE (db);
 
-	db->priv->entries = g_hash_table_new (g_str_hash, g_str_equal);
+	db->priv->entries = g_hash_table_new (rb_refstring_hash, rb_refstring_equal);
 
 	db->priv->genres = g_hash_table_new_full (g_direct_hash, g_direct_equal,
 						  NULL, (GDestroyNotify)g_hash_table_destroy);
-	db->priv->unknown_entry_types = g_hash_table_new (g_str_hash, g_str_equal);
+	db->priv->unknown_entry_types = g_hash_table_new (rb_refstring_hash, rb_refstring_equal);
 }
 
 static void
-unparent_entries (const char *uri,
+unparent_entries (gpointer key,
 		  RhythmDBEntry *entry,
 		  RhythmDBTree *db)
 {
@@ -190,7 +190,7 @@ unparent_entries (const char *uri,
 }
 
 static void
-free_unknown_entries (const char *name,
+free_unknown_entries (RBRefString *name,
 		      GList *entries,
 		      gpointer nah)
 {
@@ -200,13 +200,13 @@ free_unknown_entries (const char *name,
 		GList *p;
 
 		entry = (RhythmDBUnknownEntry *)e->data;
-		g_free (entry->typename);
+		rb_refstring_unref (entry->typename);
 		for (p = entry->properties; p != NULL; p = p->next) {
 			RhythmDBUnknownEntryProperty *prop;
 
 			prop = (RhythmDBUnknownEntryProperty *)p->data;
-			g_free (prop->name);
-			g_free (prop->value);
+			rb_refstring_unref (prop->name);
+			rb_refstring_unref (prop->value);
 			g_free (prop);
 		}
 
@@ -342,7 +342,7 @@ rhythmdb_tree_parser_start_element (stru
 				rb_debug ("reading unknown entry");
 				ctx->state = RHYTHMDB_TREE_PARSER_STATE_UNKNOWN_ENTRY;
 				ctx->unknown_entry = g_new0 (RhythmDBUnknownEntry, 1);
-				ctx->unknown_entry->typename = g_strdup (typename);
+				ctx->unknown_entry->typename = rb_refstring_new (typename);
 			}
 		} else {
 			ctx->in_unknown_elt++;
@@ -367,7 +367,7 @@ rhythmdb_tree_parser_start_element (stru
 		RhythmDBUnknownEntryProperty *prop;
 
 		prop = g_new0 (RhythmDBUnknownEntryProperty, 1);
-		prop->name = g_strdup (name);
+		prop->name = rb_refstring_new (name);
 
 		ctx->unknown_entry->properties = g_list_prepend (ctx->unknown_entry->properties, prop);
 		ctx->state = RHYTHMDB_TREE_PARSER_STATE_UNKNOWN_ENTRY_PROPERTY;
@@ -433,7 +433,8 @@ rhythmdb_tree_parser_end_element (struct
 					ctx->batch_count = 0;
 				}
 			} else {
-				rb_debug ("found entry with duplicate location %s. merging metadata", ctx->entry->location);
+				rb_debug ("found entry with duplicate location %s. merging metadata",
+					  rb_refstring_get (ctx->entry->location));
 				entry->play_count += ctx->entry->play_count;
 
 				if (entry->rating < 0.01)
@@ -523,8 +524,8 @@ rhythmdb_tree_parser_end_element (struct
 		g_assert (ctx->unknown_entry->properties);
 		prop = ctx->unknown_entry->properties->data;
 		g_assert (prop->value == NULL);
-		prop->value = g_strdup (ctx->buf->str);
-		rb_debug ("unknown entry property: %s = %s", prop->name, prop->value);
+		prop->value = rb_refstring_new (ctx->buf->str);
+		rb_debug ("unknown entry property: %s = %s", rb_refstring_get (prop->name), rb_refstring_get (prop->value));
 
 		ctx->state = RHYTHMDB_TREE_PARSER_STATE_UNKNOWN_ENTRY;
 		break;
@@ -825,7 +826,7 @@ save_entry (RhythmDBTree *db,
 			save_entry_double(ctx, elt_name, entry->album_peak);
 			break;
 		case RHYTHMDB_PROP_LOCATION:
-			save_entry_string(ctx, elt_name, entry->location);
+			save_entry_string(ctx, elt_name, rb_refstring_get (entry->location));
 			break;
 		case RHYTHMDB_PROP_MOUNTPOINT:
 			/* Avoid crashes on exit when upgrading from 0.8
@@ -933,7 +934,7 @@ save_entry_type (const char *name,
 }
 
 static void
-save_unknown_entry_type (const char *typename,
+save_unknown_entry_type (RBRefString *typename,
 			 GList *entries,
 			 struct RhythmDBTreeSaveContext *ctx)
 {
@@ -950,7 +951,7 @@ save_unknown_entry_type (const char *typ
 		entry = (RhythmDBUnknownEntry *)t->data;
 
 		RHYTHMDB_FWRITE_STATICSTR ("  <entry type=\"", ctx->handle, ctx->error);
-		encoded	= xmlEncodeEntitiesReentrant (NULL, BAD_CAST entry->typename);
+		encoded	= xmlEncodeEntitiesReentrant (NULL, BAD_CAST rb_refstring_get (entry->typename));
 		RHYTHMDB_FWRITE (encoded, 1, xmlStrlen (encoded), ctx->handle, ctx->error);
 		g_free (encoded);
 
@@ -959,7 +960,7 @@ save_unknown_entry_type (const char *typ
 		for (p = entry->properties; p != NULL; p = p->next) {
 			RhythmDBUnknownEntryProperty *prop;
 			prop = (RhythmDBUnknownEntryProperty *) p->data;
-			save_entry_string(ctx, (const xmlChar *)prop->name, prop->value);
+			save_entry_string(ctx, (const xmlChar *)rb_refstring_get (prop->name), rb_refstring_get (prop->value));
 		}
 
 		RHYTHMDB_FWRITE_STATICSTR ("  </entry>\n", ctx->handle, ctx->error);
@@ -1068,23 +1069,23 @@ rhythmdb_tree_entry_new (RhythmDB *rdb,
 	g_return_if_fail (entry->location != NULL);
 
 	if (entry->title == NULL) {
-		g_warning ("Entry %s has missing title",entry->location);
+		g_warning ("Entry %s has missing title", rb_refstring_get (entry->location));
 		entry->title = rb_refstring_new (_("Unknown"));
 	}
 	if (entry->artist == NULL) {
-		g_warning ("Entry %s has missing artist",entry->location);
+		g_warning ("Entry %s has missing artist", rb_refstring_get (entry->location));
 		entry->artist = rb_refstring_new (_("Unknown"));
 	}
 	if (entry->album == NULL) {
-		g_warning ("Entry %s has missing album",entry->location);
+		g_warning ("Entry %s has missing album", rb_refstring_get (entry->location));
 		entry->album = rb_refstring_new (_("Unknown"));
 	}
 	if (entry->genre == NULL) {
-		g_warning ("Entry %s has missing genre",entry->location);
+		g_warning ("Entry %s has missing genre", rb_refstring_get (entry->location));
 		entry->genre = rb_refstring_new (_("Unknown"));
 	}
 	if (entry->mimetype == NULL) {
-		g_warning ("Entry %s has missing mimetype",entry->location);
+		g_warning ("Entry %s has missing mimetype", rb_refstring_get (entry->location));
 		entry->mimetype = rb_refstring_new ("unknown/unknown");
 	}
 
@@ -1290,17 +1291,17 @@ rhythmdb_tree_entry_set (RhythmDB *adb,
 	{
 	case RHYTHMDB_PROP_LOCATION:
 	{
+		RBRefString *s;
 		/* We have to use the string in the entry itself as the hash key,
 		 * otherwise either we leak it, or the string vanishes when the
 		 * GValue is freed; this means we have to do the entry modification
 		 * here, rather than letting rhythmdb_entry_set_internal do it.
 		 */
-		g_assert (g_hash_table_lookup (db->priv->entries, entry->location) != NULL);
-
-		g_hash_table_remove (db->priv->entries, entry->location);
+		g_assert (g_hash_table_remove (db->priv->entries, entry->location));
 
-		g_free (entry->location);
-		entry->location = g_strdup (g_value_get_string (value));
+		s = rb_refstring_new (g_value_get_string (value));
+		rb_refstring_unref (entry->location);
+		entry->location = s;
 		g_hash_table_insert (db->priv->entries, entry->location, entry);
 
 		return TRUE;
@@ -1394,9 +1395,7 @@ rhythmdb_tree_entry_delete (RhythmDB *ad
 
 	remove_entry_from_album (db, entry);
 
-	g_assert (g_hash_table_lookup (db->priv->entries, entry->location) != NULL);
-
-	g_hash_table_remove (db->priv->entries, entry->location);
+	g_assert (g_hash_table_remove (db->priv->entries, entry->location));
 	rhythmdb_entry_unref (entry);
 }
 
@@ -1406,7 +1405,7 @@ typedef struct {
 } RbEntryRemovalCtxt;
 
 static gboolean
-remove_one_song (gchar *uri,
+remove_one_song (gpointer key,
 		 RhythmDBEntry *entry,
 		 RbEntryRemovalCtxt *ctxt)
 {
@@ -2023,7 +2022,7 @@ rhythmdb_tree_do_full_query (RhythmDB *a
 
 static RhythmDBEntry *
 rhythmdb_tree_entry_lookup_by_location (RhythmDB *adb,
-					const char *uri)
+					RBRefString *uri)
 {
 	RhythmDBTree *db = RHYTHMDB_TREE (adb);
 	return g_hash_table_lookup (db->priv->entries, uri);
@@ -2175,15 +2174,19 @@ rhythmdb_tree_entry_type_registered (Rhy
 				     const char *name,
 				     RhythmDBEntryType entry_type)
 {
-	GList *entries;
+	GList *entries = NULL;
 	GList *e;
 	gint count = 0;
 	RhythmDBTree *rdb;
+	RBRefString *rs_name;
+
 	if (name == NULL)
 		return;
 
 	rdb = RHYTHMDB_TREE (db);
-	entries = g_hash_table_lookup (rdb->priv->unknown_entry_types, name);
+	rs_name = rb_refstring_find (name);
+	if (rs_name)
+		entries = g_hash_table_lookup (rdb->priv->unknown_entry_types, rs_name);
 	if (entries == NULL) {
 		rb_debug ("no entries of newly registered type %s loaded from db", name);
 		return;
@@ -2203,9 +2206,9 @@ rhythmdb_tree_entry_type_registered (Rhy
 			GValue value = {0,};
 
 			prop = (RhythmDBUnknownEntryProperty *) p->data;
-			propid = rhythmdb_propid_from_nice_elt_name (db, (const xmlChar *) prop->name);
+			propid = rhythmdb_propid_from_nice_elt_name (db, (const xmlChar *) rb_refstring_get (prop->name));
 
-			rhythmdb_read_encoded_property (db, prop->value, propid, &value);
+			rhythmdb_read_encoded_property (db, rb_refstring_get (prop->value), propid, &value);
 			rhythmdb_entry_set_internal (db, entry, FALSE, propid, &value);
 			g_value_unset (&value);
 		}
@@ -2216,6 +2219,6 @@ rhythmdb_tree_entry_type_registered (Rhy
 	rb_debug ("handled %d entries of newly registered type %s", count, name);
 	rhythmdb_commit (db);
 
-	g_hash_table_remove (rdb->priv->unknown_entry_types, name);
-	free_unknown_entries (name, entries, NULL);
+	g_hash_table_remove (rdb->priv->unknown_entry_types, rs_name);
+	free_unknown_entries (rs_name, entries, NULL);
 }
diff -u -p -r1.241 rhythmdb.c
--- rhythmdb/rhythmdb.c	23 Jul 2006 16:02:59 -0000	1.241
+++ rhythmdb/rhythmdb.c	24 Jul 2006 09:25:42 -0000
@@ -77,7 +77,7 @@ typedef struct
 		RHYTHMDB_ACTION_LOAD,
 		RHYTHMDB_ACTION_SYNC
 	} type;
-	char *uri;
+	RBRefString *uri;
  	RhythmDBEntryType entry_type;
 } RhythmDBAction;
 
@@ -451,7 +451,7 @@ rhythmdb_execute_multi_stat_info_cb (Gno
 		if (info_result->result == GNOME_VFS_OK) {
 			event->vfsinfo = gnome_vfs_file_info_dup (info_result->file_info);
 		} else {
-			char *unescaped = gnome_vfs_unescape_string_for_display (event->real_uri);
+			char *unescaped = gnome_vfs_unescape_string_for_display (rb_refstring_get (event->real_uri));
 			event->error = g_error_new (RHYTHMDB_ERROR,
 						    RHYTHMDB_ERROR_ACCESS_FAILED,
 						    _("Couldn't access %s: %s"),
@@ -522,8 +522,8 @@ rhythmdb_event_free (RhythmDB *db,
 	}
 	if (result->error)
 		g_error_free (result->error);
-	g_free (result->uri);
-	g_free (result->real_uri);
+	rb_refstring_unref (result->uri);
+	rb_refstring_unref (result->real_uri);
 	if (result->vfsinfo)
 		gnome_vfs_file_info_unref (result->vfsinfo);
 	if (result->metadata)
@@ -786,7 +786,7 @@ sync_entry_changed (RhythmDBEntry *entry
 
 			action = g_new0 (RhythmDBAction, 1);
 			action->type = RHYTHMDB_ACTION_SYNC;
-			action->uri = g_strdup (entry->location);
+			action->uri = rb_refstring_ref (entry->location);
 			g_async_queue_push (db->priv->action_queue, action);
 			break;
 		}
@@ -1087,7 +1087,7 @@ rhythmdb_entry_new (RhythmDB *db,
 	}
 
 	ret = rhythmdb_entry_allocate (db, type);
-	ret->location = g_strdup (uri);
+	ret->location = rb_refstring_new (uri);
 	klass->impl_entry_new (db, ret);
 	rb_debug ("emitting entry added");
 	rhythmdb_entry_insert (db, ret);
@@ -1116,7 +1116,7 @@ rhythmdb_entry_example_new (RhythmDB *db
 	RhythmDBEntry *ret;
 
 	ret = rhythmdb_entry_allocate (db, type);
-	ret->location = g_strdup (uri);
+	ret->location = rb_refstring_new (uri);
 
 	if (type == RHYTHMDB_ENTRY_TYPE_SONG) {
 		rb_refstring_unref (ret->artist);
@@ -1160,8 +1160,8 @@ rhythmdb_entry_finalize (RhythmDBEntry *
 	if (type->pre_entry_destroy)
 		(type->pre_entry_destroy)(entry, type->pre_entry_destroy_data);
 
-	g_free (entry->location);
-	g_free (entry->playback_error);
+	rb_refstring_unref (entry->location);
+	rb_refstring_unref (entry->playback_error);
 	rb_refstring_unref (entry->title);
 	rb_refstring_unref (entry->genre);
 	rb_refstring_unref (entry->artist);
@@ -1439,7 +1439,7 @@ rhythmdb_process_stat_event (RhythmDB *d
 	RhythmDBEntry *entry;
 	RhythmDBAction *action;
 
-	entry = rhythmdb_entry_lookup_by_location (db, event->real_uri);
+	entry = rhythmdb_entry_lookup_by_location_refstring (db, event->real_uri);
 	if (entry) {
 		time_t mtime = (time_t) entry->mtime;
 
@@ -1453,7 +1453,7 @@ rhythmdb_process_stat_event (RhythmDB *d
 			if (!is_ghost_entry (entry)) {
 				rhythmdb_entry_set_visibility (db, entry, FALSE);
 			} else {
-				rb_debug ("error accessing %s: %s", event->real_uri,
+				rb_debug ("error accessing %s: %s", rb_refstring_get (event->real_uri),
 					  event->error->message);
 				rhythmdb_entry_delete (db, entry);
 			}
@@ -1471,7 +1471,7 @@ rhythmdb_process_stat_event (RhythmDB *d
 			mount_point = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_MOUNTPOINT);
 			if (mount_point == NULL) {
 				rhythmdb_entry_set_mount_point (db, entry,
-								event->real_uri);
+								rb_refstring_get (event->real_uri));
 			}
 
 			/* Update last seen time. It will also be updated
@@ -1494,17 +1494,17 @@ rhythmdb_process_stat_event (RhythmDB *d
 			g_value_unset (&val);
 
 			if (mtime == event->vfsinfo->mtime) {
-				rb_debug ("not modified: %s", event->real_uri);
+				rb_debug ("not modified: %s", rb_refstring_get (event->real_uri));
 				/* monitor the file for changes */
 				if (eel_gconf_get_boolean (CONF_MONITOR_LIBRARY))
-					rhythmdb_monitor_uri_path (db, entry->location, NULL /* FIXME */);
+					rhythmdb_monitor_uri_path (db, rb_refstring_get (entry->location), NULL /* FIXME */);
 			} else {
 				RhythmDBEvent *new_event;
 
-				rb_debug ("changed: %s", event->real_uri);
+				rb_debug ("changed: %s", rb_refstring_get (event->real_uri));
 				new_event = g_new0 (RhythmDBEvent, 1);
 				new_event->db = db;
-				new_event->uri = g_strdup (event->real_uri);
+				new_event->uri = rb_refstring_ref (event->real_uri);
 				new_event->type = RHYTHMDB_EVENT_FILE_CREATED_OR_MODIFIED;
 				g_async_queue_push (db->priv->event_queue,
 						    new_event);
@@ -1515,9 +1515,9 @@ rhythmdb_process_stat_event (RhythmDB *d
 	} else {
 		action = g_new0 (RhythmDBAction, 1);
 		action->type = RHYTHMDB_ACTION_LOAD;
-		action->uri = g_strdup (event->real_uri);
+		action->uri = rb_refstring_ref (event->real_uri);
 		action->entry_type = event->entry_type;
-		rb_debug ("queuing a RHYTHMDB_ACTION_LOAD: %s", action->uri);
+		rb_debug ("queuing a RHYTHMDB_ACTION_LOAD: %s", rb_refstring_get (action->uri));
 		g_async_queue_push (db->priv->action_queue, action);
 	}
 }
@@ -1546,13 +1546,13 @@ rhythmdb_add_import_error_entry (RhythmD
 		error_entry_type = RHYTHMDB_ENTRY_TYPE_IGNORE;
 	}
 
-	entry = rhythmdb_entry_lookup_by_location (db, event->real_uri);
+	entry = rhythmdb_entry_lookup_by_location_refstring (db, event->real_uri);
 	if (entry) {
 		RhythmDBEntryType entry_type = rhythmdb_entry_get_entry_type (entry);
 		if (entry_type != RHYTHMDB_ENTRY_TYPE_IMPORT_ERROR &&
 		    entry_type != RHYTHMDB_ENTRY_TYPE_IGNORE) {
 			/* FIXME we've successfully read this file before.. so what should we do? */
-			rb_debug ("%s already exists in the library.. ignoring import error?", event->real_uri);
+			rb_debug ("%s already exists in the library.. ignoring import error?", rb_refstring_get (event->real_uri));
 			return;
 		}
 
@@ -1583,7 +1583,7 @@ rhythmdb_add_import_error_entry (RhythmD
 
 	if (entry == NULL) {
 		/* create a new import error or ignore entry */
-		entry = rhythmdb_entry_new (db, error_entry_type, event->real_uri);
+		entry = rhythmdb_entry_new (db, error_entry_type, rb_refstring_get (event->real_uri));
 		if (entry == NULL)
 			return;
 
@@ -1606,7 +1606,7 @@ rhythmdb_add_import_error_entry (RhythmD
 		}
 
 		/* record the mount point so we can delete entries for unmounted volumes */
-		rhythmdb_entry_set_mount_point (db, entry, event->real_uri);
+		rhythmdb_entry_set_mount_point (db, entry, rb_refstring_get (event->real_uri));
 
 		rhythmdb_entry_set_visibility (db, entry, TRUE);
 
@@ -1643,7 +1643,7 @@ rhythmdb_process_metadata_load (RhythmDB
 
 	g_get_current_time (&time);
 
-	entry = rhythmdb_entry_lookup_by_location (db, event->real_uri);
+	entry = rhythmdb_entry_lookup_by_location_refstring (db, event->real_uri);
 
 	if (entry != NULL) {
 		if ((event->entry_type != RHYTHMDB_ENTRY_TYPE_INVALID) &&
@@ -1659,7 +1659,7 @@ rhythmdb_process_metadata_load (RhythmDB
 		if (event->entry_type == RHYTHMDB_ENTRY_TYPE_INVALID)
 			event->entry_type = RHYTHMDB_ENTRY_TYPE_SONG;
 
-		entry = rhythmdb_entry_new (db, event->entry_type, event->real_uri);
+		entry = rhythmdb_entry_new (db, event->entry_type, rb_refstring_get (event->real_uri));
 		if (entry == NULL) {
 			rb_debug ("entry already exists");
 			return TRUE;
@@ -1710,12 +1710,12 @@ rhythmdb_process_metadata_load (RhythmDB
 	g_value_unset (&value);
 
 	/* Remember the mount point of the volume the song is on */
-	rhythmdb_entry_set_mount_point (db, entry, event->real_uri);
+	rhythmdb_entry_set_mount_point (db, entry, rb_refstring_get (event->real_uri));
 
 	/* monitor the file for changes */
 	/* FIXME: watch for errors */
 	if (eel_gconf_get_boolean (CONF_MONITOR_LIBRARY) && event->entry_type == RHYTHMDB_ENTRY_TYPE_SONG)
-		rhythmdb_monitor_uri_path (db, entry->location, NULL);
+		rhythmdb_monitor_uri_path (db, rb_refstring_get (entry->location), NULL);
 
 	rhythmdb_add_timeout_commit (db, FALSE);
 
@@ -1745,7 +1745,7 @@ rhythmdb_process_file_created_or_modifie
 
 	action = g_new0 (RhythmDBAction, 1);
 	action->type = RHYTHMDB_ACTION_LOAD;
-	action->uri = g_strdup (event->uri);
+	action->uri = rb_refstring_ref (event->uri);
 	action->entry_type = RHYTHMDB_ENTRY_TYPE_INVALID;
 	g_async_queue_push (db->priv->action_queue, action);
 }
@@ -1754,12 +1754,12 @@ static void
 rhythmdb_process_file_deleted (RhythmDB *db,
 			       RhythmDBEvent *event)
 {
-	RhythmDBEntry *entry = rhythmdb_entry_lookup_by_location (db, event->uri);
+	RhythmDBEntry *entry = rhythmdb_entry_lookup_by_location_refstring (db, event->uri);
 
-	g_hash_table_remove (db->priv->changed_files, event->uri);
+	g_hash_table_remove (db->priv->changed_files, rb_refstring_get (event->uri));
 
 	if (entry) {
-		rb_debug ("deleting entry for %s", event->uri);
+		rb_debug ("deleting entry for %s", rb_refstring_get (event->uri));
 		rhythmdb_entry_set_visibility (db, entry, FALSE);
 		rhythmdb_commit (db);
 	}
@@ -1927,7 +1927,7 @@ rhythmdb_execute_stat_info_cb (GnomeVFSA
 	if (info_result->result == GNOME_VFS_OK) {
 		event->vfsinfo = gnome_vfs_file_info_dup (info_result->file_info);
 	} else {
-		char *unescaped = gnome_vfs_unescape_string_for_display (event->real_uri);
+		char *unescaped = gnome_vfs_unescape_string_for_display (rb_refstring_get (event->real_uri));
 		event->error = g_error_new (RHYTHMDB_ERROR,
 					    RHYTHMDB_ERROR_ACCESS_FAILED,
 					    _("Couldn't access %s: %s"),
@@ -1948,7 +1948,7 @@ rhythmdb_execute_stat (RhythmDB *db,
 	GnomeVFSURI *vfs_uri = gnome_vfs_uri_new (uri);
 
 	GList *uri_list = g_list_append (NULL, vfs_uri);
-	event->real_uri = g_strdup (uri);
+	event->real_uri = rb_refstring_new (uri);
 
 	gnome_vfs_async_get_file_info (&event->handle, uri_list,
 			       GNOME_VFS_FILE_INFO_FOLLOW_LINKS,
@@ -2003,7 +2003,7 @@ queue_stat_uri (const char *uri,
 			g_free (result);
 			gnome_vfs_uri_unref (vfs_uri);
 		} else {
-			result->real_uri = g_strdup (uri);
+			result->real_uri = rb_refstring_new (uri);
 			g_hash_table_insert (db->priv->stat_events, vfs_uri, result);
 			db->priv->stat_list = g_list_prepend (db->priv->stat_list, vfs_uri);
 		}
@@ -2045,7 +2045,7 @@ rhythmdb_execute_load (RhythmDB *db,
 	GnomeVFSURI *vfs_uri = gnome_vfs_uri_new (uri);
 	GnomeVFSResult vfsresult;
 
-	event->real_uri = rb_uri_resolve_symlink (uri);
+	event->real_uri = rb_refstring_new (rb_uri_resolve_symlink (uri));
 	event->vfsinfo = gnome_vfs_file_info_new ();
 
 	vfsresult = gnome_vfs_get_file_info (uri,
@@ -2066,7 +2066,7 @@ rhythmdb_execute_load (RhythmDB *db,
 	} else {
 		if (event->type == RHYTHMDB_EVENT_METADATA_LOAD) {
 			event->metadata = rb_metadata_new ();
-			rb_metadata_load (event->metadata, event->real_uri,
+			rb_metadata_load (event->metadata, rb_refstring_get (event->real_uri),
 					  &event->error);
 		}
 	}
@@ -2184,9 +2184,9 @@ action_thread_main (RhythmDB *db)
 			result->type = RHYTHMDB_EVENT_STAT;
 			result->entry_type = action->entry_type;
 
-			rb_debug ("executing RHYTHMDB_ACTION_STAT for \"%s\"", action->uri);
+			rb_debug ("executing RHYTHMDB_ACTION_STAT for \"%s\"", rb_refstring_get (action->uri));
 
-			rhythmdb_execute_stat (db, action->uri, result);
+			rhythmdb_execute_stat (db, rb_refstring_get (action->uri), result);
 		}
 		break;
 		case RHYTHMDB_ACTION_LOAD:
@@ -2196,9 +2196,9 @@ action_thread_main (RhythmDB *db)
 			result->type = RHYTHMDB_EVENT_METADATA_LOAD;
 			result->entry_type = action->entry_type;
 
-			rb_debug ("executing RHYTHMDB_ACTION_LOAD for \"%s\"", action->uri);
+			rb_debug ("executing RHYTHMDB_ACTION_LOAD for \"%s\"", rb_refstring_get (action->uri));
 
-			rhythmdb_execute_load (db, action->uri, result);
+			rhythmdb_execute_load (db, rb_refstring_get (action->uri), result);
 		}
 		break;
 		case RHYTHMDB_ACTION_SYNC:
@@ -2212,7 +2212,7 @@ action_thread_main (RhythmDB *db)
 				break;
 			}
 
-			entry = rhythmdb_entry_lookup_by_location (db, action->uri);
+			entry = rhythmdb_entry_lookup_by_location_refstring (db, action->uri);
 			if (!entry)
 				break;
 
@@ -2225,7 +2225,7 @@ action_thread_main (RhythmDB *db)
 				data = g_new0 (RhythmDBSaveErrorData, 1);
 				g_object_ref (db);
 				data->db = db;
-				data->uri = g_strdup (action->uri);
+				data->uri = g_strdup (rb_refstring_get (action->uri));
 				data->error = error;
 				g_idle_add ((GSourceFunc)emit_save_error_idle, data);
 				break;
@@ -2635,13 +2635,13 @@ rhythmdb_entry_set_internal (RhythmDB *d
 			entry->album_peak = g_value_get_double (value);
 			break;
 		case RHYTHMDB_PROP_LOCATION:
-			g_free (entry->location);
-			entry->location = g_value_dup_string (value);
+			rb_refstring_unref (entry->location);
+			entry->location = rb_refstring_new (g_value_get_string (value));
 			break;
 		case RHYTHMDB_PROP_PLAYBACK_ERROR:
-			g_free (entry->playback_error);
+			rb_refstring_unref (entry->playback_error);
 			if (g_value_get_string (value))
-				entry->playback_error = g_value_dup_string (value);
+				entry->playback_error = rb_refstring_new (g_value_get_string (value));
 			else
 				entry->playback_error = NULL;
 			break;
@@ -2913,7 +2913,7 @@ rhythmdb_entry_move_to_trash_set_error (
 	rhythmdb_entry_set (db, entry, RHYTHMDB_PROP_PLAYBACK_ERROR, &value);
 	g_value_unset (&value);
 
-	rb_debug ("Deleting %s failed: %s", entry->location,
+	rb_debug ("Deleting %s failed: %s", rb_refstring_get (entry->location),
 			gnome_vfs_result_to_string (res));
 }
 
@@ -2925,7 +2925,7 @@ rhythmdb_entry_move_to_trash (RhythmDB *
 	GnomeVFSURI *uri, *trash, *dest;
 	char *shortname;
 
-	uri = gnome_vfs_uri_new (entry->location);
+	uri = gnome_vfs_uri_new (rb_refstring_get (entry->location));
 	if (uri == NULL) {
 		rhythmdb_entry_move_to_trash_set_error (db, entry, -1);
 		return;
@@ -3056,6 +3056,18 @@ RhythmDBEntry *
 rhythmdb_entry_lookup_by_location (RhythmDB *db,
 				   const char *uri)
 {
+	RBRefString *rs;
+
+	rs = rb_refstring_find (uri);
+	if (rs)
+		return rhythmdb_entry_lookup_by_location_refstring (db, rs);
+	else
+		return NULL;
+}
+
+RhythmDBEntry *
+rhythmdb_entry_lookup_by_location_refstring (RhythmDB *db, RBRefString *uri)
+{
 	RhythmDBClass *klass = RHYTHMDB_GET_CLASS (db);
 
 	return klass->impl_lookup_by_location (db, uri);
@@ -3500,7 +3512,7 @@ default_sync_metadata (RhythmDB *db,
 		/* reload the metadata, to revert the db changes */
 		load_action = g_new0 (RhythmDBAction, 1);
 		load_action->type = RHYTHMDB_ACTION_LOAD;
-		load_action->uri = g_strdup (uri);
+		load_action->uri = rb_refstring_ref (entry->location);
 		load_action->entry_type = RHYTHMDB_ENTRY_TYPE_INVALID;
 		g_async_queue_push (db->priv->action_queue, load_action);
 
@@ -3894,13 +3906,13 @@ rhythmdb_entry_get_string (RhythmDBEntry
 	case RHYTHMDB_PROP_GENRE_FOLDED:
 		return rb_refstring_get_folded (entry->genre);
 	case RHYTHMDB_PROP_LOCATION:
-		return entry->location;
+		return rb_refstring_get (entry->location);
 	case RHYTHMDB_PROP_MOUNTPOINT:
 		return rb_refstring_get (entry->mountpoint);
 	case RHYTHMDB_PROP_LAST_PLAYED_STR:
 		return rb_refstring_get (entry->last_played_str);
 	case RHYTHMDB_PROP_PLAYBACK_ERROR:
-		return entry->playback_error;
+		return rb_refstring_get (entry->playback_error);
 	case RHYTHMDB_PROP_FIRST_SEEN_STR:
 		return rb_refstring_get (entry->first_seen_str);
 	case RHYTHMDB_PROP_LAST_SEEN_STR:
@@ -3939,6 +3951,46 @@ rhythmdb_entry_get_string (RhythmDBEntry
 		else
 			return NULL;
 
+	default:
+		g_assert_not_reached ();
+		return NULL;
+	}
+}
+
+RBRefString *
+rhythmdb_entry_get_refstring (RhythmDBEntry *entry,
+			      RhythmDBPropType propid)
+{
+	g_return_val_if_fail (entry != NULL, NULL);
+	g_return_val_if_fail (entry->refcount > 0, NULL);
+
+	rhythmdb_entry_sync_mirrored (entry, propid);
+
+	switch (propid) {
+	case RHYTHMDB_PROP_TITLE:
+		return rb_refstring_ref (entry->title);
+	case RHYTHMDB_PROP_ALBUM:
+		return rb_refstring_ref (entry->album);
+	case RHYTHMDB_PROP_ARTIST:
+		return rb_refstring_ref (entry->artist);
+	case RHYTHMDB_PROP_GENRE:
+		return rb_refstring_ref (entry->genre);
+	case RHYTHMDB_PROP_MUSICBRAINZ_TRACKID:
+		return rb_refstring_ref (entry->musicbrainz_trackid);
+	case RHYTHMDB_PROP_MIMETYPE:
+		return rb_refstring_ref (entry->mimetype);
+	case RHYTHMDB_PROP_MOUNTPOINT:
+		return rb_refstring_ref (entry->mountpoint);
+	case RHYTHMDB_PROP_LAST_PLAYED_STR:
+		return rb_refstring_ref (entry->last_played_str);
+	case RHYTHMDB_PROP_FIRST_SEEN_STR:
+		return rb_refstring_ref (entry->first_seen_str);
+	case RHYTHMDB_PROP_LAST_SEEN_STR:
+		return rb_refstring_ref (entry->last_seen_str);
+	case RHYTHMDB_PROP_LOCATION:
+		return rb_refstring_ref (entry->location);
+	case RHYTHMDB_PROP_PLAYBACK_ERROR:
+		return rb_refstring_ref (entry->playback_error);
 	default:
 		g_assert_not_reached ();
 		return NULL;
diff -u -p -r1.94 rhythmdb.h
--- rhythmdb/rhythmdb.h	23 Jul 2006 16:03:00 -0000	1.94
+++ rhythmdb/rhythmdb.h	24 Jul 2006 09:25:42 -0000
@@ -28,6 +28,7 @@
 #include <libxml/tree.h>
 
 #include "config.h"
+#include "rb-refstring.h"
 #include "rhythmdb-query-results.h"
 
 G_BEGIN_DECLS
@@ -216,6 +217,7 @@ typedef struct {
 } RhythmDBEntryChange;
 
 const char *rhythmdb_entry_get_string	(RhythmDBEntry *entry, RhythmDBPropType propid);
+RBRefString *rhythmdb_entry_get_refstring (RhythmDBEntry *entry, RhythmDBPropType propid);
 char *rhythmdb_entry_dup_string	(RhythmDBEntry *entry, RhythmDBPropType propid);
 gboolean rhythmdb_entry_get_boolean	(RhythmDBEntry *entry, RhythmDBPropType propid);
 guint64 rhythmdb_entry_get_uint64	(RhythmDBEntry *entry, RhythmDBPropType propid);
@@ -274,7 +276,7 @@ typedef struct
 
 	void            (*impl_entry_delete_by_type) (RhythmDB *db, RhythmDBEntryType type);
 
-	RhythmDBEntry *	(*impl_lookup_by_location)(RhythmDB *db, const char *uri);
+	RhythmDBEntry *	(*impl_lookup_by_location)(RhythmDB *db, RBRefString *uri);
 
 	gboolean 	(*impl_evaluate_query)	(RhythmDB *db, GPtrArray *query, RhythmDBEntry *entry);
 
diff -u -p -r1.467 rb-shell.c
--- shell/rb-shell.c	23 Jul 2006 16:04:14 -0000	1.467
+++ shell/rb-shell.c	24 Jul 2006 09:25:44 -0000
@@ -1705,11 +1705,14 @@ rb_shell_db_entry_added_cb (RhythmDB *db
 			    RhythmDBEntry *entry,
 			    RBShell *shell)
 {
+	const char *loc;
+
 	if (shell->priv->pending_entry == NULL)
 		return;
 
-	rb_debug ("got entry added for %s", entry->location);
-	if (strcmp (entry->location, shell->priv->pending_entry) == 0) {
+	loc = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+	rb_debug ("got entry added for %s", loc);
+	if (strcmp (loc, shell->priv->pending_entry) == 0) {
 		rb_shell_play_entry (shell, entry);
 
 		g_free (shell->priv->pending_entry);
diff -u -p -r1.127 rb-playlist-source.c
--- sources/rb-playlist-source.c	23 Jul 2006 16:04:45 -0000	1.127
+++ sources/rb-playlist-source.c	24 Jul 2006 09:25:47 -0000
@@ -244,7 +244,8 @@ rb_playlist_source_constructor (GType ty
 	g_object_unref (db);
 	g_object_unref (shell);
 
-	source->priv->entries = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	source->priv->entries = g_hash_table_new_full (rb_refstring_hash, rb_refstring_equal,
+						       (GDestroyNotify)rb_refstring_unref, NULL);
 
 	source->priv->songs = rb_entry_view_new (source->priv->db, shell_player,
 					 	 NULL, TRUE, TRUE);
@@ -682,15 +683,16 @@ rb_playlist_source_row_deleted (GtkTreeM
 				RBPlaylistSource *source)
 {
 	RhythmDBEntry *entry;
-	const char *location;
+	RBRefString *location;
 
 	entry = rhythmdb_query_model_tree_path_to_entry (RHYTHMDB_QUERY_MODEL (model),
 							 path);
 
-	location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+	location = rhythmdb_entry_get_refstring (entry, RHYTHMDB_PROP_LOCATION);
 	if (g_hash_table_remove (source->priv->entries, location))
 		source->priv->dirty = TRUE;
 
+	rb_refstring_unref (location);
 	rhythmdb_entry_unref (entry);
 }
 
@@ -699,14 +701,16 @@ rb_playlist_source_entry_added_cb (Rhyth
 				   RhythmDBEntry *entry,
 				   RBPlaylistSource *source)
 {
-	const char *location;
+	RBRefString *location;
 
-	location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+	location = rhythmdb_entry_get_refstring (entry, RHYTHMDB_PROP_LOCATION);
 
 	if (g_hash_table_lookup (source->priv->entries, location)) {
 		rhythmdb_query_model_add_entry (source->priv->model, entry, -1);
 		source->priv->dirty = TRUE;
 	}
+
+	rb_refstring_unref (location);
 }
 
 static void
@@ -791,18 +795,31 @@ gboolean
 rb_playlist_source_location_in_map (RBPlaylistSource *source,
 				    const char *location)
 {
-	return (g_hash_table_lookup (source->priv->entries, location) != NULL);
+	RBRefString *refstr;
+	gboolean found;
+
+	refstr = rb_refstring_find (location);
+	if (!refstr)
+		return FALSE;
+
+	found = (g_hash_table_lookup (source->priv->entries, refstr) != NULL);
+	rb_refstring_unref (refstr);
+	return found;
 }
 
 gboolean
 rb_playlist_source_add_to_map (RBPlaylistSource *source,
 			       const char *location)
 {
-	if (g_hash_table_lookup (source->priv->entries, location)) {
+	RBRefString *refstr;
+
+	refstr = rb_refstring_new (location);
+	if (g_hash_table_lookup (source->priv->entries, refstr)) {
+		rb_refstring_unref (refstr);
 		return FALSE;
 	}
 
 	g_hash_table_insert (source->priv->entries,
-			     g_strdup (location), GINT_TO_POINTER (1));
+			     refstr, GINT_TO_POINTER (1));
 	return TRUE;
 }
