[Banshee-List] Making move operation saver



Due to bug #562791 I looked at the "MoveOnInfoSaveJob" today and got quite worried about the race conditions that seem to exist in the current implementation. Attached is a patch that first copies the file and after everything is saved successfully deletes the old one. In general looking at the other jobs, it seems like Banshee solely relies on sqlite's consistency but too less on it's own. IMO some parts of the code would need to be changed into a more transactional approach.

P.S. Hope it's more convenient now ;)

diff --git a/src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs b/src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs
index 2e77747..dd281c8 100644
--- a/src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs
+++ b/src/Core/Banshee.Services/Banshee.Collection/MoveOnInfoSaveJob.cs
@@ -66,12 +66,41 @@ namespace Banshee.Collection
             string new_filename = FileNamePattern.BuildFull (track, Path.GetExtension (old_uri.ToString ()));
             SafeUri new_uri = new SafeUri (new_filename);
 
-            if (!new_uri.Equals (old_uri) && !Banshee.IO.File.Exists (new_uri)) {
-                Banshee.IO.File.Move (old_uri, new_uri);
-                Banshee.IO.Utilities.TrimEmptyDirectories (old_uri);
+            if (new_uri.Equals (old_uri)) {
+                return;
+            }
+
+            //in theory we should check whether on an exception
+            //the new file already contains the data of the old one
+            //but since that's currently not implemented just fail
+            Banshee.IO.File.Copy (old_uri, new_uri, false);
+
+            try
+            {   
                 track.Uri = new_uri;
                 track.Save ();
             }
+            catch(Exception ex)
+            {
+                // possible inconsistency - rollback changes
+		Rollback(old_uri, new_uri);
+                throw ex;
+            }
+            
+            Banshee.IO.File.Delete (old_uri);
+            Banshee.IO.Utilities.TrimEmptyDirectories (old_uri);
         }
+
+	private void Rollback(SafeUri old_uri, SafeUri new_uri)
+	{
+            try
+            {
+                Banshee.IO.File.Delete (new_uri);
+            }
+            catch(Exception)
+            {
+                //can't do more than try
+            }
+	}
     }
 }


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