Fixed problems with missing empty directories due to incorrect LocalFileComparer...
authorPanagiotis Kanavos <pkanavos@gmail.com>
Mon, 12 Mar 2012 19:01:43 +0000 (21:01 +0200)
committerPanagiotis Kanavos <pkanavos@gmail.com>
Mon, 12 Mar 2012 19:01:43 +0000 (21:01 +0200)
Fixes #2197

trunk/Pithos.Core.Test/LocalFileComparerTest.cs [new file with mode: 0644]
trunk/Pithos.Core.Test/Pithos.Core.Test.csproj
trunk/Pithos.Core/Agents/FileSystemWatcherAdapter.cs
trunk/Pithos.Core/Agents/PollAgent.cs
trunk/Pithos.Core/LocalFileComparer.cs [new file with mode: 0644]
trunk/Pithos.Core/Pithos.Core.csproj
trunk/Pithos.Core/PithosMonitor.cs

diff --git a/trunk/Pithos.Core.Test/LocalFileComparerTest.cs b/trunk/Pithos.Core.Test/LocalFileComparerTest.cs
new file mode 100644 (file)
index 0000000..a7db6a2
--- /dev/null
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Pithos.Interfaces;
+using Pithos.Network;
+
+namespace Pithos.Core.Test
+{
+    [TestFixture]
+    class LocalFileComparerTest
+    {
+        [Test]
+        public void objects_with_same_name_and_hash_should_match()
+        {
+            var comparer = new LocalFileComparer();
+            var account = new AccountInfo();
+            var x = new Agents.CloudDownloadAction(account, new ObjectInfo {Account="a",Container="c",Name = "x", Hash = "a"});
+            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "x", Hash = "a" });
+            Assert.That(comparer.Equals(x, y), Is.True);
+        }
+
+        [Test]
+        public void objects_with_different_name_same_hash_should_not_match()
+        {
+            var comparer = new LocalFileComparer();
+            var account = new AccountInfo();
+            var x = new Agents.CloudDownloadAction(account, new ObjectInfo {Account="a",Container="c",Name = "x", Hash = "a"});
+            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "y", Hash = "a" });
+            Assert.That(comparer.Equals(x, y), Is.True);
+        }
+        [Test]
+        public void directories_with_different_name_should_not_match()
+        {
+            var comparer = new LocalFileComparer();
+            var account = new AccountInfo();
+            var x = new Agents.CloudDownloadAction(account, new ObjectInfo {Account="a",Container="c",Name = "x", Hash = "a",Content_Type = "application/directory"});
+            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "y", Hash = "a", Content_Type = "application/directory" });
+            Assert.That(comparer.Equals(x, y), Is.False);
+        }
+
+    }
+}
index e888b79..4b91404 100644 (file)
     <Compile Include="ExtensionTests.cs" />
     <Compile Include="FileSystemWatcherAdapterTest.cs" />
     <Compile Include="IdleBatchTest.cs" />
+    <Compile Include="LocalFileComparerTest.cs" />
     <Compile Include="NetworkAgentTest.cs" />
     <Compile Include="PithosWorkflowTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
index 2b69050..6d8860e 100644 (file)
@@ -94,7 +94,6 @@ namespace Pithos.Core.Agents
                 throw new ArgumentException("e");\r
             if (string.IsNullOrWhiteSpace(e.FullPath))\r
                 throw new ArgumentException("e");\r
-            Contract.Ensures(!String.IsNullOrWhiteSpace(_cachedDeletedFullPath));\r
             Contract.EndContractBlock();\r
 \r
             TaskEx.Run(() => InnerOnDeleted(sender, e));\r
@@ -134,7 +133,6 @@ namespace Pithos.Core.Agents
         {\r
             if (sender == null)\r
                 throw new ArgumentNullException("sender");\r
-            Contract.Ensures(_cachedDeletedFullPath == null);\r
             Contract.EndContractBlock();\r
 \r
             TaskEx.Run(() => InnerRename(sender, e));\r
@@ -196,7 +194,6 @@ namespace Pithos.Core.Agents
                 throw new ArgumentNullException("sender");\r
             if (!(e.ChangeType == WatcherChangeTypes.Created || e.ChangeType == WatcherChangeTypes.Changed))\r
                 throw new ArgumentException("e");\r
-            Contract.Ensures(_cachedDeletedFullPath == null);\r
             Contract.EndContractBlock();\r
             TaskEx.Run(() => InnerChangeOrCreated(sender, e));\r
 \r
index 3d3cb1b..06d5663 100644 (file)
@@ -189,7 +189,7 @@ namespace Pithos.Core.Agents
             Contract.EndContractBlock();\r
 \r
 \r
-            using (log4net.ThreadContext.Stacks["Retrieve Remote"].Push(accountInfo.UserName))\r
+            using (ThreadContext.Stacks["Retrieve Remote"].Push(accountInfo.UserName))\r
             {\r
 \r
                 await NetworkAgent.GetDeleteAwaiter();\r
@@ -228,7 +228,7 @@ namespace Pithos.Core.Agents
                     listObjects.Add(listShared);\r
                     var listTasks = await Task.Factory.WhenAll(listObjects.ToArray());\r
 \r
-                    using (log4net.ThreadContext.Stacks["SCHEDULE"].Push("Process Results"))\r
+                    using (ThreadContext.Stacks["SCHEDULE"].Push("Process Results"))\r
                     {\r
                         var dict = listTasks.ToDictionary(t => t.AsyncState);\r
 \r
@@ -285,7 +285,7 @@ namespace Pithos.Core.Agents
 \r
                         //And remove those that are already being processed by the agent\r
                         var distinctActions = allActions\r
-                            .Except(NetworkAgent.GetEnumerable(), new PithosMonitor.LocalFileComparer())\r
+                            .Except(NetworkAgent.GetEnumerable(), new LocalFileComparer())\r
                             .ToList();\r
 \r
                         //Queue all the actions\r
@@ -540,10 +540,14 @@ namespace Pithos.Core.Agents
             //over the remote files\r
             foreach (var objectInfo in creates)\r
             {\r
+                if (Log.IsDebugEnabled)\r
+                    Log.DebugFormat("[NEW INFO] {0}",objectInfo.Uri);\r
+\r
                 var relativePath = objectInfo.RelativeUrlToFilePath(accountInfo.UserName);\r
                 //If the object already exists, we probably have a conflict\r
                 if (fileAgent.Exists(relativePath))\r
                 {\r
+                    Log.DebugFormat("[SKIP EXISTING] {0}", objectInfo.Uri);\r
                     //If a directory object already exists, we don't need to perform any other action                    \r
                     var localFile = fileAgent.GetFileSystemInfo(relativePath);\r
                     StatusKeeper.SetFileState(localFile.FullName, FileStatus.Conflict, FileOverlayStatus.Conflict);\r
@@ -608,6 +612,8 @@ namespace Pithos.Core.Agents
         {\r
             AccountInfo account;\r
             _accounts.TryRemove(accountInfo.UserName,out account);\r
+            SnapshotDifferencer differencer;\r
+            _differencer.Differencers.TryRemove(accountInfo.UserName, out differencer);\r
         }\r
     }\r
 }\r
diff --git a/trunk/Pithos.Core/LocalFileComparer.cs b/trunk/Pithos.Core/LocalFileComparer.cs
new file mode 100644 (file)
index 0000000..5a13de8
--- /dev/null
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using Pithos.Core.Agents;
+
+namespace Pithos.Core
+{
+    public class LocalFileComparer:EqualityComparer<CloudAction>
+    {
+        public override bool Equals(CloudAction x, CloudAction y)
+        {
+            if (x.Action != y.Action)
+                return false;
+            if (x.LocalFile != null && y.LocalFile != null && !x.LocalFile.FullName.Equals(y.LocalFile.FullName))
+                return false;
+            if (x.CloudFile != null && y.CloudFile != null )
+            {
+                if (x.CloudFile.Hash == null & y.CloudFile.Hash != null)
+                    return false;
+                if (x.CloudFile.Hash != null & y.CloudFile.Hash == null)
+                    return false;
+                if (x.CloudFile.Hash == null & y.CloudFile.Hash == null)
+                    return (x.CloudFile.Name == y.CloudFile.Name);
+                    
+                if (!x.CloudFile.Hash.Equals(y.CloudFile.Hash))
+                    return false;
+                //All directories have the same hash. Compare them using their names instead
+                if (x.CloudFile.Content_Type == y.CloudFile.Content_Type && x.CloudFile.Content_Type == "application/directory")
+                {
+                    return (x.CloudFile.Name == y.CloudFile.Name);
+                }
+            }
+            if (x.CloudFile == null ^ y.CloudFile == null ||
+                x.LocalFile == null ^ y.LocalFile == null)
+                return false;
+            return true;
+        }
+
+        public override int GetHashCode(CloudAction obj)
+        {
+            if (obj == null)
+                return 0;
+            var hash1 = (obj.LocalFile == null) ? Int32.MaxValue : obj.LocalFile.FullName.GetHashCode();
+            var hash2 = Int32.MaxValue;
+            if (obj.CloudFile != null)
+            {
+                //All directories have the same hash code. Use their name's hash code instead
+                hash2 = obj.CloudFile.Content_Type == "application/directory" 
+                            ? obj.CloudFile.Name.GetHashCode() 
+                            : (obj.CloudFile.Hash ?? obj.CloudFile.Name ?? "").GetHashCode();
+            }
+            var hash3 = obj.Action.GetHashCode();
+            return hash1 ^ hash2 & hash3;
+        }
+    }
+}
\ No newline at end of file
index 532eeb3..016ce3b 100644 (file)
     <Compile Include="IStatusNotification.cs" />
     <Compile Include="IStatusService.cs" />
     <Compile Include="JobQueue.cs" />
+    <Compile Include="LocalFileComparer.cs" />
     <Compile Include="NetworkGate.cs" />
     <Compile Include="Agents\StatusAgent.cs" />
     <Compile Include="IPithosWorkflow.cs" />
index a81428f..ce0acd1 100644 (file)
@@ -317,42 +317,6 @@ namespace Pithos.Core
             }
         }*/
 
-        internal class LocalFileComparer:EqualityComparer<CloudAction>
-        {
-            public override bool Equals(CloudAction x, CloudAction y)
-            {
-                if (x.Action != y.Action)
-                    return false;
-                if (x.LocalFile != null && y.LocalFile != null && !x.LocalFile.FullName.Equals(y.LocalFile.FullName))
-                    return false;
-                if (x.CloudFile != null && y.CloudFile != null )
-                {
-                    if (x.CloudFile.Hash == null & y.CloudFile.Hash != null)
-                        return false;
-                    if (x.CloudFile.Hash != null & y.CloudFile.Hash == null)
-                        return false;
-                    if (x.CloudFile.Hash == null & y.CloudFile.Hash == null)
-                        return (x.CloudFile.Name == y.CloudFile.Name);
-                    if (!x.CloudFile.Hash.Equals(y.CloudFile.Hash))
-                        return false;
-                }
-                if (x.CloudFile == null ^ y.CloudFile == null ||
-                    x.LocalFile == null ^ y.LocalFile == null)
-                    return false;
-                return true;
-            }
-
-            public override int GetHashCode(CloudAction obj)
-            {
-                if (obj == null)
-                    return 0;
-                var hash1 = (obj.LocalFile == null) ? int.MaxValue : obj.LocalFile.FullName.GetHashCode();
-                var hash2 = (obj.CloudFile == null) ? int.MaxValue : (obj.CloudFile.Hash ?? obj.CloudFile.Name??"").GetHashCode();
-                var hash3 = obj.Action.GetHashCode();
-                return hash1 ^ hash2 & hash3;
-            }
-        }        
-
 
         private void StartNetworkAgent()
         {