[tracker] Make sure the fd isn't closed as long as the lock stays.



commit 0fec5bf4e7211344059459bb2ab4f69d8de241b7
Author: Carlos Garnacho <carlos lanedo com>
Date:   Mon Nov 23 14:43:00 2009 +0100

    Make sure the fd isn't closed as long as the lock stays.

 src/libtracker-common/tracker-file-utils.c     |   85 ++++++++++++++----------
 src/tracker-writeback/tracker-writeback-file.c |   17 +++++-
 2 files changed, 66 insertions(+), 36 deletions(-)
---
diff --git a/src/libtracker-common/tracker-file-utils.c b/src/libtracker-common/tracker-file-utils.c
index 5c5a36d..f58537a 100644
--- a/src/libtracker-common/tracker-file-utils.c
+++ b/src/libtracker-common/tracker-file-utils.c
@@ -45,6 +45,8 @@
 
 #define TEXT_SNIFF_SIZE 4096
 
+static GHashTable *file_locks = NULL;
+
 FILE *
 tracker_file_open (const gchar *uri,
 		   const gchar *how,
@@ -690,70 +692,80 @@ tracker_env_check_xdg_dirs (void)
 	return success;
 }
 
-static int
-flock_file (GFile *file,
-	    gint   flags)
+gboolean
+tracker_file_lock (GFile *file)
 {
-	gchar *path;
 	gint fd, retval;
+	gchar *path;
+
+	g_return_val_if_fail (G_IS_FILE (file), FALSE);
+
+	if (G_UNLIKELY (!file_locks)) {
+		file_locks = g_hash_table_new_full ((GHashFunc) g_file_hash,
+						    (GEqualFunc) g_file_equal,
+						    (GDestroyNotify) g_object_unref,
+						    NULL);
+	}
 
-	g_return_val_if_fail (G_IS_FILE (file), -1);
+	/* Don't try to lock twice */
+	if (g_hash_table_lookup (file_locks, file) != NULL) {
+		return TRUE;
+	}
 
 	if (!g_file_is_native (file)) {
-		return -1;
+		return FALSE;
 	}
 
 	path = g_file_get_path (file);
 
 	if (!path) {
-		return -1;
+		return FALSE;
 	}
 
 	fd = open (path, O_RDONLY);
 
 	if (fd < 0) {
-		g_warning ("Could not open '%s'", path);
-		retval = -1;
+ 		g_warning ("Could not open '%s'", path);
+		g_free (path);
+
+		return FALSE;
+	}
+
+	retval = flock (fd, LOCK_EX);
+
+	if (retval == 0) {
+		g_hash_table_insert (file_locks,
+				     g_object_ref (file),
+				     GINT_TO_POINTER (fd));
 	} else {
-		retval = flock (fd, flags);
-		close (fd);
+		g_warning ("Could not lock file '%s'", path);
+ 		close (fd);
 	}
 
 	g_free (path);
 
-	return retval;
+	return (retval == 0);
 }
 
 gboolean
-tracker_file_lock (GFile *file)
+tracker_file_unlock (GFile *file)
 {
-	gint retval;
+	gint retval, fd;
 
-	g_return_val_if_fail (G_IS_FILE (file), FALSE);
+	g_return_val_if_fail (G_IS_FILE (file), TRUE);
 
-	retval = flock_file (file, LOCK_EX);
+	if (!file_locks) {
+		return TRUE;
+ 	}
 
-	if (retval < 0) {
-		gchar *path;
+	fd = GPOINTER_TO_INT (g_hash_table_lookup (file_locks, file));
 
-		path = g_file_get_path (file);
-		g_warning ("Could not lock file '%s'", path);
-		g_free (path);
-
-		return FALSE;
+	if (fd == 0) {
+		/* File wasn't actually locked */
+		return TRUE;
 	}
 
-	return TRUE;
-}
-
-gboolean
-tracker_file_unlock (GFile *file)
-{
-	gint retval;
-
-	g_return_val_if_fail (G_IS_FILE (file), FALSE);
-
-	retval = flock_file (file, LOCK_UN);
+	retval = flock (fd, LOCK_UN);
 
 	if (retval < 0) {
 		gchar *path;
@@ -765,6 +777,9 @@ tracker_file_unlock (GFile *file)
 		return FALSE;
 	}
 
+	g_hash_table_remove (file_locks, file);
+	close (fd);
+
 	return TRUE;
 }
 
@@ -797,7 +812,7 @@ tracker_file_is_locked (GFile *file)
 	}
 
 	/* Check for locks */
-	retval = flock (fd, LOCK_EX | LOCK_NB);
+	retval = flock (fd, LOCK_SH | LOCK_NB);
 
 	if (retval < 0) {
 		if (errno == EWOULDBLOCK) {
diff --git a/src/tracker-writeback/tracker-writeback-file.c b/src/tracker-writeback/tracker-writeback-file.c
index a6b370e..cae2736 100644
--- a/src/tracker-writeback/tracker-writeback-file.c
+++ b/src/tracker-writeback/tracker-writeback-file.c
@@ -43,6 +43,21 @@ tracker_writeback_file_init (TrackerWritebackFile *writeback_file)
 }
 
 static gboolean
+unlock_file_cb (GFile *file)
+{
+	gchar *path;
+
+	path = g_file_get_path (file);
+	g_message ("Unlocking file '%s'", path);
+	g_free (path);
+
+	tracker_file_unlock (file);
+	g_object_unref (file);
+
+	return FALSE;
+}
+
+static gboolean
 tracker_writeback_file_update_metadata (TrackerWriteback *writeback,
                                         GPtrArray        *values)
 {
@@ -77,7 +92,7 @@ tracker_writeback_file_update_metadata (TrackerWriteback *writeback,
 	retval = (writeback_file_class->update_file_metadata) (TRACKER_WRITEBACK_FILE (writeback),
 	                                                       file, values);
 
-	tracker_file_unlock (file);
+	g_timeout_add_seconds (3, (GSourceFunc) unlock_file_cb, g_object_ref (file));
 
 	g_object_unref (file);
 



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