[banshee] LibraryWatcher: avoid importing incomplete files



commit cf2346be3df5ec3f196d4129e288214aeacd56e5
Author: Andres G. Aragoneses <knocte gmail com>
Date:   Tue Feb 21 01:25:07 2012 +0000

    LibraryWatcher: avoid importing incomplete files
    
    LibraryWatcher had a bug that is usually found in any library that uses
    FileSystemWatcher API: handling files at the Creation event rather than
    at the last Changed one (when the file transfer/creation has really been
    finished in the watched folder). In Banshee this could have the effect
    of trying to import incomplete files and not reading their tags
    correctly obviously. This bug manifested itself much more clearly when
    the new feature in bgo#664079 was implemented: warning when the user
    tried to import an empty file (as this was implemented raising an
    exception from the importing logic), causing the symptoms described in
    bgo#666981.
    
    With this fix we introduce a timer to delay the handling of the FSW
    event just a small amount of time (10s), and we reset the timer every
    time a Changed event happens, in order to handle the Create event
    only at the last Changed event. This patch may even fix the broader
    bug filed at bgo#655752.
    
    Signed-off-by: Bertrand Lorentz <bertrand lorentz gmail com>

 .../Banshee.LibraryWatcher/SourceWatcher.cs        |   60 ++++++++++++++++++-
 1 files changed, 56 insertions(+), 4 deletions(-)
---
diff --git a/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/SourceWatcher.cs b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/SourceWatcher.cs
index 859e05f..8bcba5d 100644
--- a/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/SourceWatcher.cs
+++ b/src/Extensions/Banshee.LibraryWatcher/Banshee.LibraryWatcher/SourceWatcher.cs
@@ -135,8 +135,62 @@ namespace Banshee.LibraryWatcher
 
 #region Private Methods
 
+        private readonly double MAX_TIME_BETWEEN_CHANGED_EVENTS = TimeSpan.FromSeconds (10).TotalMilliseconds;
+
+        Dictionary<string, System.Timers.Timer> created_items_bag = new Dictionary<string, System.Timers.Timer> ();
+
+        private System.Timers.Timer CreateTimer (string fullpath)
+        {
+            var timer = new System.Timers.Timer (MAX_TIME_BETWEEN_CHANGED_EVENTS);
+            timer.Elapsed += (sender, e) => TimeUpForChangedEvent (fullpath);
+            return timer;
+        }
+
+        private void OnCreation (string fullpath)
+        {
+            var timer = CreateTimer (fullpath);
+            lock (created_items_bag) {
+                created_items_bag [fullpath] = timer;
+            }
+            timer.AutoReset = false;
+            timer.Start ();
+        }
+
+        private void TimeUpForChangedEvent (string fullpath)
+        {
+            lock (created_items_bag) {
+                created_items_bag [fullpath].Stop ();
+                created_items_bag [fullpath].Dispose ();
+                created_items_bag.Remove (fullpath);
+            }
+            var fake_args = new FileSystemEventArgs (WatcherChangeTypes.Created,
+                                                     System.IO.Path.GetDirectoryName (fullpath),
+                                                     System.IO.Path.GetFileName (fullpath));
+            EnqueueAffectedElement (fake_args);
+        }
+
         private void OnModified (object source, FileSystemEventArgs args)
         {
+            if (args.ChangeType == WatcherChangeTypes.Created) {
+                OnCreation (args.FullPath);
+                return;
+            } else if (args.ChangeType == WatcherChangeTypes.Changed) {
+                lock (created_items_bag) {
+                    System.Timers.Timer timer;
+                    if (created_items_bag.TryGetValue (args.FullPath, out timer)) {
+                        // A file we saw being created was modified, restart the timer
+                        timer.Stop ();
+                        timer.Start ();
+                        return;
+                    }
+                }
+            }
+
+            EnqueueAffectedElement (args);
+        }
+
+        private void EnqueueAffectedElement (FileSystemEventArgs args)
+        {
             var item = new QueueItem {
                 When = DateTime.Now,
                 ChangeType = args.ChangeType,
@@ -149,10 +203,8 @@ namespace Banshee.LibraryWatcher
             }
             handle.Set ();
 
-            if (args.ChangeType != WatcherChangeTypes.Changed) {
-                Hyena.Log.DebugFormat ("Watcher: {0} {1}{2}",
-                    item.ChangeType, args is RenamedEventArgs ? item.OldFullPath + " => " : "", item.FullPath);
-            }
+            Hyena.Log.DebugFormat ("Watcher: {0} {1}{2}",
+                item.ChangeType, args is RenamedEventArgs ? item.OldFullPath + " => " : "", item.FullPath);
         }
 
         private void Watch ()



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