[rhythmbox] rhythmdb: move most file-not-found/mount/unmount processing inside entry types



commit 1abb391e51f94deda1e237d6754b09d784a106ca
Author: Jonathan Matthew <jonathan d14n org>
Date:   Sun Aug 8 22:19:13 2010 +1000

    rhythmdb: move most file-not-found/mount/unmount processing inside entry types

 rhythmdb/rhythmdb-monitor.c          |   42 +++---------
 rhythmdb/rhythmdb-song-entry-types.c |  126 +++++++++++++++++++++++++++++++++-
 rhythmdb/rhythmdb.c                  |   74 ++------------------
 3 files changed, 141 insertions(+), 101 deletions(-)
---
diff --git a/rhythmdb/rhythmdb-monitor.c b/rhythmdb/rhythmdb-monitor.c
index 380d7e4..23646c4 100644
--- a/rhythmdb/rhythmdb-monitor.c
+++ b/rhythmdb/rhythmdb-monitor.c
@@ -418,7 +418,7 @@ typedef struct
 {
 	RhythmDB *db;
 	RBRefString *mount_point;
-	gboolean mounted;
+	RhythmDBEntryAvailability avail;
 } MountCtxt;
 
 static void
@@ -426,48 +426,26 @@ entry_volume_mounted_or_unmounted (RhythmDBEntry *entry,
 				   MountCtxt *ctxt)
 {
 	RBRefString *mount_point;
-	const char *location;
 
 	mount_point = rhythmdb_entry_get_refstring (entry, RHYTHMDB_PROP_MOUNTPOINT);
 	if (mount_point == NULL || !rb_refstring_equal (mount_point, ctxt->mount_point)) {
 		return;
 	}
-	location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
 
-	if (entry->type == RHYTHMDB_ENTRY_TYPE_SONG) {
-		if (ctxt->mounted) {
-			rb_debug ("queueing stat for entry %s (mounted)", location);
+	rhythmdb_entry_update_availability (entry, ctxt->avail);
+	rhythmdb_commit (ctxt->db);
 
-			/* make files visible immediately,
-			 * then hide any that turn out to be missing.
-			 */
-			rhythmdb_entry_set_visibility (ctxt->db, entry, TRUE);
+	/* check local files when mounted */
+	if (ctxt->avail == RHYTHMDB_ENTRY_AVAIL_MOUNTED) {
+		const char *location = rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION);
+		if (rb_uri_is_local (location)) {
 			rhythmdb_add_uri_with_types (ctxt->db,
 						     location,
 						     RHYTHMDB_ENTRY_TYPE_SONG,
 						     RHYTHMDB_ENTRY_TYPE_IGNORE,
 						     RHYTHMDB_ENTRY_TYPE_IMPORT_ERROR);
-		} else {
-			GTimeVal time;
-			GValue val = {0, };
-
-			rb_debug ("hiding entry %s (unmounted)", location);
-
-			g_get_current_time (&time);
-			g_value_init (&val, G_TYPE_ULONG);
-			g_value_set_ulong (&val, time.tv_sec);
-			rhythmdb_entry_set_internal (ctxt->db, entry, FALSE,
-						     RHYTHMDB_PROP_LAST_SEEN, &val);
-			g_value_unset (&val);
-
-			rhythmdb_entry_set_visibility (ctxt->db, entry, FALSE);
-		}
-	} else if (entry->type == RHYTHMDB_ENTRY_TYPE_IMPORT_ERROR) {
-		/* delete import errors for files on unmounted volumes */
-		if (ctxt->mounted == FALSE) {
-			rb_debug ("removing import error for %s (unmounted)", location);
-			rhythmdb_entry_delete (ctxt->db, entry);
 		}
+
 	}
 }
 
@@ -488,7 +466,7 @@ rhythmdb_mount_added_cb (GVolumeMonitor *monitor,
 	g_free (mp);
 
 	ctxt.db = db;
-	ctxt.mounted = TRUE;
+	ctxt.avail = RHYTHMDB_ENTRY_AVAIL_MOUNTED;
 	rb_debug ("volume %s mounted", rb_refstring_get (ctxt.mount_point));
 	rhythmdb_entry_foreach_by_type (db,
 					RHYTHMDB_ENTRY_TYPE_SONG,
@@ -519,7 +497,7 @@ rhythmdb_mount_removed_cb (GVolumeMonitor *monitor,
 	g_free (mp);
 
 	ctxt.db = db;
-	ctxt.mounted = FALSE;
+	ctxt.avail = RHYTHMDB_ENTRY_AVAIL_UNMOUNTED;
 	rb_debug ("volume %s unmounted", rb_refstring_get (ctxt.mount_point));
 	rhythmdb_entry_foreach_by_type (db,
 					RHYTHMDB_ENTRY_TYPE_SONG,
diff --git a/rhythmdb/rhythmdb-song-entry-types.c b/rhythmdb/rhythmdb-song-entry-types.c
index 8bdeada..1ed629b 100644
--- a/rhythmdb/rhythmdb-song-entry-types.c
+++ b/rhythmdb/rhythmdb-song-entry-types.c
@@ -28,15 +28,69 @@
 
 #include "config.h"
 
+#include <gconf/gconf-client.h>
+
 #include "rhythmdb-entry-type.h"
 #include "rhythmdb-private.h"
+#include "rb-preferences.h"
 #include "rb-util.h"
+#include "rb-debug.h"
 
 static RhythmDBEntryType *song_entry_type = NULL;
 static RhythmDBEntryType *error_entry_type = NULL;
 static RhythmDBEntryType *ignore_entry_type = NULL;
 
 static void
+update_entry_last_seen (RhythmDB *db, RhythmDBEntry *entry)
+{
+	GTimeVal time;
+	GValue val = {0, };
+
+	g_get_current_time (&time);
+	g_value_init (&val, G_TYPE_ULONG);
+	g_value_set_ulong (&val, time.tv_sec);
+	rhythmdb_entry_set_internal (db, entry, FALSE, RHYTHMDB_PROP_LAST_SEEN, &val);
+	g_value_unset (&val);
+}
+
+static gboolean
+check_entry_grace_period (RhythmDB *db, RhythmDBEntry *entry)
+{
+	GTimeVal time;
+	gulong last_seen;
+	gulong grace_period;
+	GError *error;
+	GConfClient *client;
+
+	client = gconf_client_get_default ();
+	if (client == NULL) {
+		return FALSE;
+	}
+	error = NULL;
+	grace_period = gconf_client_get_int (client, CONF_GRACE_PERIOD,
+					     &error);
+	g_object_unref (G_OBJECT (client));
+	if (error != NULL) {
+		g_error_free (error);
+		return FALSE;
+	}
+
+	/* This is a bit silly, but I prefer to make sure we won't
+	 * overflow in the following calculations
+	 */
+	if ((grace_period <= 0) || (grace_period > 20000)) {
+		return FALSE;
+	}
+
+	/* Convert from days to seconds */
+	grace_period = grace_period * 60 * 60 * 24;
+	g_get_current_time (&time);
+	last_seen = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_LAST_SEEN);
+
+	return (last_seen + grace_period < time.tv_sec);
+}
+
+static void
 song_sync_metadata (RhythmDBEntryType *entry_type,
 		    RhythmDBEntry *entry,
 		    GSList *changes,
@@ -67,6 +121,74 @@ song_can_sync_metadata (RhythmDBEntryType *entry_type,
 	return can_sync;
 }
 
+static void
+song_update_availability (RhythmDBEntryType *entry_type,
+			  RhythmDBEntry *entry,
+			  RhythmDBEntryAvailability avail)
+{
+	RhythmDB *db;
+
+	g_object_get (entry_type, "db", &db, NULL);
+	switch (avail) {
+	case RHYTHMDB_ENTRY_AVAIL_MOUNTED:
+		rhythmdb_entry_set_visibility (db, entry, TRUE);
+		break;
+
+	case RHYTHMDB_ENTRY_AVAIL_CHECKED:
+		update_entry_last_seen (db, entry);
+		rhythmdb_entry_set_visibility (db, entry, TRUE);
+		break;
+
+	case RHYTHMDB_ENTRY_AVAIL_UNMOUNTED:
+		/* update the last-seen time if the entry is currently visible */
+		if (rhythmdb_entry_get_boolean (entry, RHYTHMDB_PROP_HIDDEN) == FALSE) {
+			update_entry_last_seen (db, entry);
+		}
+		rhythmdb_entry_set_visibility (db, entry, FALSE);
+		break;
+
+	case RHYTHMDB_ENTRY_AVAIL_NOT_FOUND:
+		if (check_entry_grace_period (db, entry)) {
+			rb_debug ("deleting entry %s; not seen for too long",
+				  rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
+			rhythmdb_entry_delete (db, entry);
+		} else {
+			rhythmdb_entry_set_visibility (db, entry, FALSE);
+		}
+		break;
+
+	default:
+		g_assert_not_reached ();
+	}
+	g_object_unref (db);
+}
+
+static void
+import_error_update_availability (RhythmDBEntryType *entry_type,
+				  RhythmDBEntry *entry,
+				  RhythmDBEntryAvailability avail)
+{
+	RhythmDB *db;
+
+	switch (avail) {
+	case RHYTHMDB_ENTRY_AVAIL_MOUNTED:
+	case RHYTHMDB_ENTRY_AVAIL_CHECKED:
+		/* do nothing; should never happen anyway */
+		break;
+	case RHYTHMDB_ENTRY_AVAIL_UNMOUNTED:
+	case RHYTHMDB_ENTRY_AVAIL_NOT_FOUND:
+		/* no need to keep error entries if the file is unavailable */
+		g_object_get (entry_type, "db", &db, NULL);
+		rhythmdb_entry_delete (db, entry);
+		g_object_unref (db);
+		break;
+
+	default:
+		g_assert_not_reached ();
+	}
+}
+
+
 /**
  * rhythmdb_get_song_entry_type:
  *
@@ -123,6 +245,7 @@ rhythmdb_register_song_entry_types (RhythmDB *db)
 					NULL);
 	song_entry_type->can_sync_metadata = song_can_sync_metadata;
 	song_entry_type->sync_metadata = song_sync_metadata;
+	song_entry_type->update_availability = song_update_availability;
 
 	ignore_entry_type = g_object_new (RHYTHMDB_TYPE_ENTRY_TYPE,
 					  "db", db,
@@ -131,6 +254,7 @@ rhythmdb_register_song_entry_types (RhythmDB *db)
 					  "category", RHYTHMDB_ENTRY_VIRTUAL,
 					  NULL);
 	ignore_entry_type->get_playback_uri = (RhythmDBEntryTypeStringFunc) rb_null_function;
+	ignore_entry_type->update_availability = song_update_availability;
 
 	error_entry_type = g_object_new (RHYTHMDB_TYPE_ENTRY_TYPE,
 					 "db", db,
@@ -140,7 +264,7 @@ rhythmdb_register_song_entry_types (RhythmDB *db)
 	error_entry_type->get_playback_uri = (RhythmDBEntryTypeStringFunc) rb_null_function;
 	error_entry_type->can_sync_metadata = (RhythmDBEntryTypeBooleanFunc) rb_true_function;
 	error_entry_type->sync_metadata = (RhythmDBEntryTypeSyncFunc) rb_null_function;
-
+	error_entry_type->update_availability = import_error_update_availability;
 
 	rhythmdb_register_entry_type (db, song_entry_type);
 	rhythmdb_register_entry_type (db, error_entry_type);
diff --git a/rhythmdb/rhythmdb.c b/rhythmdb/rhythmdb.c
index a4a0655..31cb3ec 100644
--- a/rhythmdb/rhythmdb.c
+++ b/rhythmdb/rhythmdb.c
@@ -2086,43 +2086,6 @@ set_props_from_metadata (RhythmDB *db,
 					  "");
 }
 
-static gboolean
-is_ghost_entry (RhythmDBEntry *entry)
-{
-	GTimeVal time;
-	gulong last_seen;
-	gulong grace_period;
-	GError *error;
-	GConfClient *client;
-
-	client = gconf_client_get_default ();
-	if (client == NULL) {
-		return FALSE;
-	}
-	error = NULL;
-	grace_period = gconf_client_get_int (client, CONF_GRACE_PERIOD,
-					     &error);
-	g_object_unref (G_OBJECT (client));
-	if (error != NULL) {
-		g_error_free (error);
-		return FALSE;
-	}
-
-	/* This is a bit silly, but I prefer to make sure we won't
-	 * overflow in the following calculations
-	 */
-	if ((grace_period <= 0) || (grace_period > 20000)) {
-		return FALSE;
-	}
-
-	/* Convert from days to seconds */
-	grace_period = grace_period * 60 * 60 * 24;
-	g_get_current_time (&time);
-	last_seen = rhythmdb_entry_get_ulong (entry, RHYTHMDB_PROP_LAST_SEEN);
-
-	return (last_seen + grace_period < time.tv_sec);
-}
-
 static void
 rhythmdb_process_stat_event (RhythmDB *db,
 			     RhythmDBEvent *event)
@@ -2143,18 +2106,12 @@ rhythmdb_process_stat_event (RhythmDB *db,
 	 */
 	if (event->error) {
 		if (entry != NULL) {
-			if (!is_ghost_entry (entry)) {
-				rhythmdb_entry_set_visibility (db, entry, FALSE);
-			} else {
-				rb_debug ("error accessing %s: %s", rb_refstring_get (event->real_uri),
-					  event->error->message);
-				rhythmdb_entry_delete (db, entry);
-			}
+			rb_debug ("error accessing %s: %s",
+				  rb_refstring_get (event->real_uri),
+				  event->error->message);
+			rhythmdb_entry_update_availability (entry, RHYTHMDB_ENTRY_AVAIL_NOT_FOUND);
 			rhythmdb_commit (db);
-		} else {
-			/* erm.. */
 		}
-
 		return;
 	}
 
@@ -2167,8 +2124,6 @@ rhythmdb_process_stat_event (RhythmDB *db,
 	case G_FILE_TYPE_UNKNOWN:
 	case G_FILE_TYPE_REGULAR:
 		if (entry != NULL) {
-			GValue val = {0, };
-			GTimeVal time;
 			guint64 new_mtime;
 			guint64 new_size;
 
@@ -2179,18 +2134,7 @@ rhythmdb_process_stat_event (RhythmDB *db,
 			if (entry->type == event->ignore_type)
 				rb_debug ("ignoring %p", entry);
 
-			rhythmdb_entry_set_visibility (db, entry, TRUE);
-
-			/* Update last seen time. It will also be updated
-			 * upon saving and when a volume is unmounted.
-			 */
-			g_get_current_time (&time);
-			g_value_init (&val, G_TYPE_ULONG);
-			g_value_set_ulong (&val, time.tv_sec);
-			rhythmdb_entry_set_internal (db, entry, TRUE,
-						     RHYTHMDB_PROP_LAST_SEEN,
-						     &val);
-			g_value_unset (&val);
+			rhythmdb_entry_update_availability (entry, RHYTHMDB_ENTRY_AVAIL_CHECKED);
 
 			/* compare modification time and size to the values in the database.
 			 * if either has changed, we'll re-read the file.
@@ -2505,13 +2449,7 @@ rhythmdb_process_metadata_load (RhythmDB *db, RhythmDBEvent *event)
 		set_props_from_metadata (db, entry, event->file_info, event->metadata);
 	}
 
-	/* we've seen this entry */
-	rhythmdb_entry_set_visibility (db, entry, TRUE);
-
-	g_value_init (&value, G_TYPE_ULONG);
-	g_value_set_ulong (&value, time.tv_sec);
-	rhythmdb_entry_set_internal (db, entry, TRUE, RHYTHMDB_PROP_LAST_SEEN, &value);
-	g_value_unset (&value);
+	rhythmdb_entry_update_availability (entry, RHYTHMDB_ENTRY_AVAIL_CHECKED);
 
 	/* Remember the mount point of the volume the song is on */
 	rhythmdb_entry_set_mount_point (db, entry, rb_refstring_get (event->real_uri));



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]