Revision 1cc1e8c5

b/trunk/Pithos.Core.Test/LocalFileComparerTest.cs
16 16
        {
17 17
            var comparer = new LocalFileComparer();
18 18
            var account = new AccountInfo();
19
            var x = new Agents.CloudDownloadAction(account, new ObjectInfo {Account="a",Container="c",Name = "x", Hash = "a"},null);
20
            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "x", Hash = "a" }, null);
19
            var x = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "x", X_Object_Hash = "a" }, null);
20
            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "x", X_Object_Hash = "a" }, null);
21 21
            Assert.That(comparer.Equals(x, y), Is.True);
22 22
        }
23 23

  
......
26 26
        {
27 27
            var comparer = new LocalFileComparer();
28 28
            var account = new AccountInfo();
29
            var x = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "x", Hash = "a" }, null);
30
            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "y", Hash = "a" }, null);
29
            var x = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "x", X_Object_Hash = "a" }, null);
30
            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "y", X_Object_Hash = "a" }, null);
31 31
            Assert.That(comparer.Equals(x, y), Is.True);
32 32
        }
33 33
        [Test]
......
35 35
        {
36 36
            var comparer = new LocalFileComparer();
37 37
            var account = new AccountInfo();
38
            var x = new Agents.CloudDownloadAction(account, new ObjectInfo {Account="a",Container="c",Name = "x", Hash = "a",Content_Type = "application/directory"},null);
39
            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "y", Hash = "a", Content_Type = "application/directory" }, null);
38
            var x = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "x", X_Object_Hash = "a", Content_Type = "application/directory" }, null);
39
            var y = new Agents.CloudDownloadAction(account, new ObjectInfo { Account = "a", Container = "c", Name = "y", X_Object_Hash = "a", Content_Type = "application/directory" }, null);
40 40
            Assert.That(comparer.Equals(x, y), Is.False);
41 41
        }
42 42

  
b/trunk/Pithos.Core.Test/MockStatusKeeper.cs
82 82

  
83 83
            _statusCache[path] = FileStatus.Unchanged;
84 84
            _overlayCache[path] = FileOverlayStatus.Normal;
85
            _checksums[path] = objectInfo.Hash;
85
            _checksums[path] = objectInfo.X_Object_Hash;
86 86

  
87 87

  
88 88
        }
b/trunk/Pithos.Core.Test/SnapshotDifferencerTest.cs
29 29
        public void Setup()
30 30
        {
31 31
            _previous = new []{
32
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="1"},
33
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="2"},
34
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="3"},
35
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="4"},
36
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,Hash="aa4",Version=1,UUID="5"},
37
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="6"},
38
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="7"},
39
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="8"},
40
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="9"},
41
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="10"},
42
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="11"},
43
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="12"},
44
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="13"},
32
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="1"},
33
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="2"},
34
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="3"},
35
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="4"},
36
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="5"},
37
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="6"},
38
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="7"},
39
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="8"},
40
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="9"},
41
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="10"},
42
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="11"},
43
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="12"},
44
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="13"},
45 45
                            };
46 46
            _current = new []{
47
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="2"},
48
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="3"},
49
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=1234,Hash="aa45",Version=1,UUID="4"},
50
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name5",Bytes=123,Hash="aa5",Version=1,UUID="14"},
51
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,Hash="aa4",Version=1,UUID="5"},
52
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="6"},
53
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="7"},
54
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="9"},
55
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="10"},
56
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=1234,Hash="aa45",Version=1,UUID="11"},
57
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name5",Bytes=123,Hash="aa5",Version=1,UUID="15"},
58
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="12"},
59
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="13"},
47
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="2"},
48
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="3"},
49
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=1234,X_Object_Hash="aa45",Version=1,UUID="4"},
50
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name5",Bytes=123,X_Object_Hash="aa5",Version=1,UUID="14"},
51
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="5"},
52
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="6"},
53
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="7"},
54
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="9"},
55
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="10"},
56
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=1234,X_Object_Hash="aa45",Version=1,UUID="11"},
57
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name5",Bytes=123,X_Object_Hash="aa5",Version=1,UUID="15"},
58
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="12"},
59
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="13"},
60 60
                           };
61 61
            
62 62
        }
......
80 80
            var differencer=d1.Post(_previous).Post(_current);
81 81
            var deleted=new[]
82 82
                            {
83
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="1"},
84
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="8"},
83
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="1"},
84
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="8"},
85 85
                            };
86 86
            Assert.That(differencer.Deleted.ToList(),Is.EquivalentTo(deleted)
87 87
                .Using((IEqualityComparer) new ObjectInfoComparer()));
......
93 93
            var differencer=d1.Post(_previous).Post(_current);
94 94
            var created = new[]
95 95
                              {
96
                                  new ObjectInfo { Account = "acc1", Container = "Cont1", Name = "Name5", Bytes = 123, Hash = "aa5", Version = 1,UUID="14" },
97
                                  new ObjectInfo { Account = "acc1", Container = "Cont2", Name = "Name5", Bytes = 123, Hash = "aa5", Version = 1,UUID="15" },
96
                                  new ObjectInfo { Account = "acc1", Container = "Cont1", Name = "Name5", Bytes = 123, X_Object_Hash = "aa5", Version = 1,UUID="14" },
97
                                  new ObjectInfo { Account = "acc1", Container = "Cont2", Name = "Name5", Bytes = 123, X_Object_Hash = "aa5", Version = 1,UUID="15" },
98 98
                              };
99 99
            Assert.That(differencer.Created.ToList(), Is.EquivalentTo(created)
100 100
                .Using((IEqualityComparer)new ObjectInfoComparer()));
......
105 105
            var d1 = new SnapshotDifferencer();            
106 106
            var differencer=d1.Post(_previous).Post(_current);
107 107
            var changed = new[] { 
108
                new ObjectInfo { Account = "acc1", Container = "Cont1", Name = "Name4", Bytes = 1234, Hash = "aa45", PreviousHash="aa4", Version = 1,UUID="4" },
109
                new ObjectInfo { Account = "acc1", Container = "Cont2", Name = "Name4", Bytes = 1234, Hash = "aa45", PreviousHash="aa4", Version = 1,UUID="11" },
108
                new ObjectInfo { Account = "acc1", Container = "Cont1", Name = "Name4", Bytes = 1234, X_Object_Hash = "aa45", PreviousHash="aa4", Version = 1,UUID="4" },
109
                new ObjectInfo { Account = "acc1", Container = "Cont2", Name = "Name4", Bytes = 1234, X_Object_Hash = "aa45", PreviousHash="aa4", Version = 1,UUID="11" },
110 110
            };
111 111

  
112 112
            Comparison<ObjectInfo> comparer = (x, y) =>
......
114 114
                                                      if (x.Account == y.Account
115 115
                                                          && x.Container == y.Container
116 116
                                                          && x.Name == y.Name
117
                                                          && x.Hash == y.Hash
117
                                                          && x.X_Object_Hash == y.X_Object_Hash
118 118
                                                          && x.PreviousHash == y.PreviousHash)
119 119
                                                          return 0;
120 120
                                                      return 1;
......
128 128
        {
129 129
            var d1 = new SnapshotDifferencer();
130 130
            var current = new[]{
131
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="1"},
132
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="2"},
133
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3a",Bytes=123,Hash="aa3",Version=1,UUID="3"},
134
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="4"},
135
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,Hash="aa4",Version=1,UUID="5"},
136
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="6"},
137
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="7"},
138
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="8"},
139
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="9"},
140
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="10"},
141
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="11"},
142
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="12"},
143
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="13"},
131
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="1"},
132
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="2"},
133
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3a",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="3"},
134
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="4"},
135
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="5"},
136
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="6"},
137
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="7"},
138
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="8"},
139
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="9"},
140
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="10"},
141
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="11"},
142
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="12"},
143
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="13"},
144 144
                            };
145 145

  
146 146
            var differencer=d1.Post(_previous).Post(current);
147 147
            var moved = new[] { 
148
                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3a",Bytes=123,Hash="aa3",PreviousHash="aa3",Version=1,UUID="3"}
148
                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3a",Bytes=123,X_Object_Hash="aa3",PreviousHash="aa3",Version=1,UUID="3"}
149 149
            };
150 150

  
151 151
            Comparison<ObjectInfo> comparer = (x, y) =>
......
153 153
                                                      if (x.Account == y.Account
154 154
                                                          && x.Container == y.Container
155 155
                                                          && x.Name == y.Name
156
                                                          && x.Hash == y.Hash
156
                                                          && x.X_Object_Hash == y.X_Object_Hash
157 157
                                                          && x.PreviousHash == y.PreviousHash)
158 158
                                                          return 0;
159 159
                                                      return 1;
......
171 171
        {
172 172
            var d1 = new SnapshotDifferencer();
173 173
            var current = new[]{
174
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="1"},
175
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="2"},
176
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3a",Bytes=123,Hash="aa35",Version=1,UUID="3"},
177
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="4"},
178
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,Hash="aa4",Version=1,UUID="5"},
179
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="6"},
180
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="7"},
181
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="8"},
182
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="9"},
183
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="10"},
184
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="11"},
185
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="12"},
186
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="13"},
174
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="1"},
175
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="2"},
176
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3a",Bytes=123,X_Object_Hash="aa35",Version=1,UUID="3"},
177
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="4"},
178
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="5"},
179
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="6"},
180
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="7"},
181
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="8"},
182
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="9"},
183
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="10"},
184
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="11"},
185
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="12"},
186
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="13"},
187 187
                            };
188 188
            var unchanged = new[]{
189
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="1",PreviousHash="aa1"},
190
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="2",PreviousHash="aa2"},
191
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="4",PreviousHash="aa4"},
192
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,Hash="aa4",Version=1,UUID="5",PreviousHash="aa4"},
193
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="6",PreviousHash="aa1"},
194
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="7",PreviousHash="aa2"},
195
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="8",PreviousHash="aa1"},
196
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="9",PreviousHash="aa2"},
197
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="10",PreviousHash="aa3"},
198
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="11",PreviousHash="aa4"},
199
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="12",PreviousHash="aa1"},
200
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="13",PreviousHash="aa2"},
189
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="1",PreviousHash="aa1"},
190
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="2",PreviousHash="aa2"},
191
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="4",PreviousHash="aa4"},
192
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="5",PreviousHash="aa4"},
193
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="6",PreviousHash="aa1"},
194
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="7",PreviousHash="aa2"},
195
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="8",PreviousHash="aa1"},
196
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="9",PreviousHash="aa2"},
197
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="10",PreviousHash="aa3"},
198
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="11",PreviousHash="aa4"},
199
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="12",PreviousHash="aa1"},
200
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="13",PreviousHash="aa2"},
201 201
                            };
202 202

  
203 203
            var differencer = d1.Post(_previous).Post(current);
204 204
            var moved = new[] { 
205
                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3a",Bytes=123,Hash="aa35",PreviousHash="aa3",Version=1,UUID="3"}
205
                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3a",Bytes=123,X_Object_Hash="aa35",PreviousHash="aa3",Version=1,UUID="3"}
206 206
            };
207 207

  
208 208
            Comparison<ObjectInfo> comparer = (x, y) =>
......
210 210
                if (x.Account == y.Account
211 211
                    && x.Container == y.Container
212 212
                    && x.Name == y.Name
213
                    && x.Hash == y.Hash
213
                    && x.X_Object_Hash == y.X_Object_Hash
214 214
                    && x.PreviousHash == y.PreviousHash)
215 215
                    return 0;
216 216
                return 1;
......
227 227
        {
228 228
            var d1 = new SnapshotDifferencer();
229 229
            var current = new[]{
230
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="1"},
231
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="2"},
232
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name3",Bytes=123,Hash="aa3",Version=1,UUID="3"},
233
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="4"},
234
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,Hash="aa4",Version=1,UUID="5"},
235
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="6"},
236
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="7"},
237
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="8"},
238
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="9"},
239
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="10"},
240
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="11"},
241
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="12"},
242
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="13"},
230
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="1"},
231
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="2"},
232
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="3"},
233
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="4"},
234
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="5"},
235
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="6"},
236
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="7"},
237
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="8"},
238
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="9"},
239
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="10"},
240
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="11"},
241
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="12"},
242
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="13"},
243 243
                            };
244 244

  
245 245
            var differencer=d1.Post(_previous).Post(current);
246 246
            var moved = new[] { 
247
                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name3",Bytes=123,Hash="aa3",PreviousHash="aa3",Version=1},
247
                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name3",Bytes=123,X_Object_Hash="aa3",PreviousHash="aa3",Version=1},
248 248
            };
249 249

  
250 250
            Comparison<ObjectInfo> comparer = (x, y) =>
......
252 252
                                                      if (x.Account == y.Account
253 253
                                                          && x.Container == y.Container
254 254
                                                          && x.Name == y.Name
255
                                                          && x.Hash == y.Hash
255
                                                          && x.X_Object_Hash == y.X_Object_Hash
256 256
                                                          && x.PreviousHash == y.PreviousHash)
257 257
                                                          return 0;
258 258
                                                      return 1;
......
272 272
            var differencer=d1.Post(_previous).Post(_current);
273 273
            var unchanged = new[]
274 274
                                {
275
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="2"},
276
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="3"},
277
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="6"},
278
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="7"},  
279
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,Hash="aa4",Version=1,UUID="5"},  
280
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="9"},
281
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="10"},
282
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="12"},
283
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="13"},                                    
275
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="2"},
276
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="3"},
277
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="6"},
278
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="7"},  
279
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="5"},  
280
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="9"},
281
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="10"},
282
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="12"},
283
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="13"},                                    
284 284
                                };            
285 285
            Assert.That(differencer.Unchanged.ToList(), Is.EquivalentTo(unchanged)
286 286
                .Using((IEqualityComparer)new ObjectInfoComparer()));
......
346 346
                                };
347 347
            var deleted = new[]
348 348
                            {
349
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="1"},
350
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="2"},
351
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="3"},
352
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="4"},
349
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="1"},
350
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="2"},
351
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="3"},
352
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="4"},
353 353
                            };
354 354
            var unchanged = new[]{
355
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,Hash="aa4",Version=1,UUID="5",PreviousHash="aa4"},
356
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="6",PreviousHash="aa1"},
357
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="7",PreviousHash="aa2"},
358
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="8",PreviousHash="aa1"},
359
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="9",PreviousHash="aa2"},
360
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,Hash="aa3",Version=1,UUID="10",PreviousHash="aa3"},
361
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,Hash="aa4",Version=1,UUID="11",PreviousHash="aa4"},
362
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,Hash="aa1",Version=1,UUID="12",PreviousHash="aa1"},
363
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,Hash="aa2",Version=1,UUID="13",PreviousHash="aa2"},
355
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont1",Name="Folder1/Name1",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="5",PreviousHash="aa4"},
356
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="6",PreviousHash="aa1"},
357
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont1",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="7",PreviousHash="aa2"},
358
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="8",PreviousHash="aa1"},
359
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="9",PreviousHash="aa2"},
360
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name3",Bytes=123,X_Object_Hash="aa3",Version=1,UUID="10",PreviousHash="aa3"},
361
                                new ObjectInfo{StorageUri=_testUri,Account="acc1",Container="Cont2",Name="Name4",Bytes=123,X_Object_Hash="aa4",Version=1,UUID="11",PreviousHash="aa4"},
362
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name1",Bytes=123,X_Object_Hash="aa1",Version=1,UUID="12",PreviousHash="aa1"},
363
                                new ObjectInfo{StorageUri=_testUri,Account="acc2",Container="Cont2",Name="Name2",Bytes=123,X_Object_Hash="aa2",Version=1,UUID="13",PreviousHash="aa2"},
364 364
                            };
365 365
            var differencer = d1.Post(_previous)
366 366
                .Post(noModItems);
b/trunk/Pithos.Core/Agents/Downloader.cs
321 321
            if (localState.ShortHash != shortHash)
322 322
                return true;
323 323
            //If the top hashes differ, we have a change
324
            return (localState.Checksum != cloudFile.Hash);
324
            return (localState.Checksum != cloudFile.X_Object_Hash);
325 325
        }
326 326

  
327 327
        private static FileAgent GetFileAgent(AccountInfo accountInfo)
b/trunk/Pithos.Core/Agents/FileAgent.cs
331 331
        {
332 332
            var rootDir = new DirectoryInfo(RootPath);
333 333
            //Ensure folders appear first, to allow folder processing as soon as possilbe
334
            var monitoredFiles = (from file in rootDir.EnumerateDirectories(searchPattern, SearchOption.AllDirectories)
335
                                 where !Ignore(file.FullName)
336
                                 orderby file.FullName ascending 
337
                                 select file)
334
            var folders = (from file in rootDir.EnumerateDirectories(searchPattern, SearchOption.AllDirectories)
335
                                     where !Ignore(file.FullName)
336
                                     orderby file.FullName ascending
337
                                     select file).ToList();
338
            var files = (from file in rootDir.EnumerateFiles(searchPattern, SearchOption.AllDirectories)
339
                                  where !Ignore(file.FullName)
340
                                  orderby file.Length ascending
341
                                  select file as FileSystemInfo).ToList();
342
            var monitoredFiles = folders
338 343
                                 //Process small files first, leaving expensive large files for last
339
                                 .Concat(from file in rootDir.EnumerateFiles(searchPattern, SearchOption.AllDirectories)
340
                                         where !Ignore(file.FullName)
341
                                         orderby file.Length ascending 
342
                                         select file as FileSystemInfo);
344
                                 .Concat(files);
343 345
            return monitoredFiles;
344 346
        }                
345 347

  
......
376 378
                    return false;
377 379
            //Ignore if selective synchronization is defined, 
378 380
            //And the target file is not below any of the selective paths
379
            return !Selectives.IsSelected(AccountInfo, filePath);
381
            var ignore = !Selectives.IsSelected(AccountInfo, filePath);
382
            return ignore;
380 383
        }
381 384

  
382 385
        public bool IsUnselectedRootFolder(string filePath)
b/trunk/Pithos.Core/Agents/NetworkAgent.cs
424 424
                var cloudFile = action.CloudFile;
425 425
                var downloadPath = action.LocalFile.GetProperCapitalization();
426 426

  
427
                var cloudHash = cloudFile.Hash.ToLower();
427
                var cloudHash = cloudFile.X_Object_Hash.ToLower();
428 428
                var previousCloudHash = cloudFile.PreviousHash == null?null: cloudFile.PreviousHash.ToLower();
429 429
                var localHash = action.TreeHash.Value.TopHash.ToHashString();// LocalHash.Value.ToLower();
430 430
                //var topHash = action.TopHash.Value.ToLower();
b/trunk/Pithos.Core/Agents/PollAgent.cs
47 47
using System.IO;
48 48
using System.Linq.Expressions;
49 49
using System.Reflection;
50
using System.Security.Cryptography;
50 51
using System.Threading;
51 52
using System.Threading.Tasks;
52 53
using Castle.ActiveRecord;
......
65 66
    {
66 67
        public string FilePath { get; private set; }
67 68

  
69
        public string MD5 { get; set; }
70

  
68 71
        public string L
69 72
        {
70 73
            get { return FileState==null?null:FileState.Checksum; }
......
74 77

  
75 78
        public string S
76 79
        {
77
            get { return ObjectInfo== null ? null : ObjectInfo.Hash; }
80
            get { return ObjectInfo == null ? null : ObjectInfo.X_Object_Hash; }
78 81
        }
79 82

  
80 83
        private FileSystemInfo _fileInfo;
......
393 396
                        foreach (var tuple in tuples)
394 397
                        {
395 398
                            await _unPauseEvent.WaitAsync();
396
                            
399

  
400
                            //Set the Merkle Hash
401
                            SetMerkleHash(accountInfo, tuple);
402

  
397 403
                            SyncSingleItem(accountInfo, tuple, agent, token);
404

  
398 405
                        }
399 406

  
400 407

  
......
421 428
            }
422 429
        }
423 430

  
431
        private static void SetMerkleHash(AccountInfo accountInfo, StateTuple tuple)
432
        {
433
            //The Merkle hash for directories is that of an empty buffer
434
            if (tuple.FileInfo is DirectoryInfo)
435
                tuple.C = MERKLE_EMPTY;
436
            else if (tuple.FileState != null && tuple.MD5 == tuple.FileState.ShortHash)
437
            {
438
                //If there is a state whose MD5 matches, load the merkle hash fromthe file state
439
                //insteaf of calculating it
440
                tuple.C = tuple.FileState.Checksum;                              
441
            }
442
            else
443
            {
444
                tuple.C=Signature.CalculateTreeHash(tuple.FileInfo, accountInfo.BlockSize, accountInfo.BlockHash)
445
                                   .TopHash.ToHashString();
446
            }
447
        }
448

  
424 449
        private static List<Tuple<FileSystemInfo, string>> LoadLocalFileTuples(AccountInfo accountInfo)
425 450
        {
426 451
            using (ThreadContext.Stacks["Account Files Hashing"].Push(accountInfo.UserName))
......
429 454
                var localInfos = AgentLocator<FileAgent>.Get(accountInfo.AccountPath).EnumerateFileSystemInfos();
430 455
                //Use the queue to retry locked file hashing
431 456
                var fileQueue = new Queue<FileSystemInfo>(localInfos);
457
                var hasher = MD5.Create();
432 458

  
433 459
                var results = new List<Tuple<FileSystemInfo, string>>();
434 460

  
......
437 463
                    var file = fileQueue.Dequeue();
438 464
                    using (ThreadContext.Stacks["File"].Push(file.FullName))
439 465
                    {
466
                        /*
467
                                                Signature.CalculateTreeHash(file, accountInfo.BlockSize,
468
                                                                                                 accountInfo.BlockHash).
469
                                                                         TopHash.ToHashString()
470
                        */
440 471
                        try
441 472
                        {
442
                            var hash = (file is DirectoryInfo)
443
                                           ? "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
444
                                           : Signature.CalculateTreeHash(file, accountInfo.BlockSize,
445
                                                                         accountInfo.BlockHash)
446
                                                 .
447
                                                 TopHash.ToHashString();
473
                            //Replace MD5 here, do the calc while syncing individual files
474
                            string hash ;
475
                            if (file is DirectoryInfo)
476
                                hash = MERKLE_EMPTY;
477
                            else
478
                            {
479
                                using (var stream = (file as FileInfo).OpenRead())
480
                                {
481
                                    hash = hasher.ComputeHash(stream).ToHashString();
482
                                }
483
                            }                            
448 484
                            results.Add(Tuple.Create(file, hash));
449 485
                        }
450 486
                        catch (IOException exc)
......
504 540
                                                                            tuple.ObjectInfo,
505 541
                                                                            localFilePath, token).Wait(token);
506 542
                            //updateRecord( L = S )
507
                            StatusKeeper.UpdateFileChecksum(localFilePath, tuple.FileState==null?"":tuple.FileState.ShortHash,
508
                                                            tuple.ObjectInfo.Hash);
543
                            StatusKeeper.UpdateFileChecksum(localFilePath, tuple.ObjectInfo.ETag,
544
                                                            tuple.ObjectInfo.X_Object_Hash);
509 545

  
510 546
                            StatusKeeper.SetFileState(localFilePath, FileStatus.Unchanged,
511 547
                                                      FileOverlayStatus.Normal, "");
......
559 595
                        {
560 596
                            // (Identical Changes) Result: L = S
561 597
                            //doNothing()
562
                            StatusKeeper.UpdateFileChecksum(localFilePath, tuple.FileState == null ? "" : tuple.FileState.ShortHash,
563
                                                            tuple.ObjectInfo.Hash);
598
                            StatusKeeper.UpdateFileChecksum(localFilePath, tuple.ObjectInfo.ETag,
599
                                                            tuple.ObjectInfo.X_Object_Hash);
564 600
                            StatusKeeper.SetFileState(localFilePath, FileStatus.Unchanged,
565 601
                                                      FileOverlayStatus.Normal, "");
566 602
                        }
......
615 651
            foreach (var file in files)
616 652
            {
617 653
                var fsInfo = file.Item1;
618
                var fileHash = file.Item2;
619
                dct[fsInfo.FullName] = new StateTuple {FileInfo = fsInfo, C = fileHash};
654
                var fileHash = fsInfo is DirectoryInfo? MERKLE_EMPTY:file.Item2;
655

  
656
                dct[fsInfo.FullName] = new StateTuple {FileInfo = fsInfo, MD5 = fileHash};
620 657
            }
621 658
            foreach (var state in states)
622 659
            {
......
690 727
        //readonly AccountsDifferencer _differencer = new AccountsDifferencer();
691 728
        private Dictionary<Uri, List<Uri>> _selectiveUris = new Dictionary<Uri, List<Uri>>();
692 729
        private bool _pause;
730
        private static string MERKLE_EMPTY = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
693 731

  
694 732
        /// <summary>
695 733
        /// Deletes local files that are not found in the list of cloud files
......
874 912
                                                     previousFile, objectInfo, state, accountInfo.BlockSize,
875 913
                                                     accountInfo.BlockHash,"Poll Moves");
876 914
                        //For modified files, we need to download the changes as well
877
                        if (objectInfo.Hash!=objectInfo.PreviousHash)
915
                        if (objectInfo.X_Object_Hash != objectInfo.PreviousHash)
878 916
                            yield return new CloudDownloadAction(accountInfo,objectInfo, "Poll Moves");
879 917
                    }
880 918
                }
b/trunk/Pithos.Core/Agents/SelectiveUris.cs
65 65
            SelectivePaths[account.AccountKey] = UrisToFilePaths(account,uris);
66 66
        }
67 67

  
68
        public void AddUri(AccountInfo account,Uri uri)
69
        {
70
            var accountPath = account.AccountPath;
71
            var storageUrl = account.StorageUri.ToString();
72
            var isShared=!uri.ToString().StartsWith(storageUrl);
73
            var relativePath = account.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath();
74
            
75
            var fullPath=isShared
76
                ?Path.Combine(accountPath, FolderConstants.OthersFolder, relativePath)
77
                :Path.Combine(accountPath, relativePath.After(account.UserName + '\\'));
78
            
79
            SelectiveUris[account.AccountKey].Add(uri);
80
            SelectivePaths[account.AccountKey].Add(fullPath);
81
            
82
        }
83

  
68 84
        public bool IsSelected(AccountInfo account,ObjectInfo info)
69 85
        {
70 86
            //Shared folders should NOT be synced if selective syncing is disabled
......
97 113
                return !isShared;
98 114

  
99 115
            List<string> paths;
100
            return !SelectivePaths.TryGetValue(account.AccountKey, out paths)
101
                || paths.Count == 0
102
                || paths.Any(fullPath.IsAtOrDirectlyBelow);
116
            var hasSelectives = SelectivePaths.TryGetValue(account.AccountKey, out paths);
117
            var isSelected = !hasSelectives || paths.Count == 0 || paths.Any(fullPath.IsAtOrDirectlyBelow);
118
            return isSelected;
103 119
        }
104 120

  
105 121
        /// <summary>
......
123 139
                          where !uri.ToString().StartsWith(storageUrl)
124 140
                          let relativePath = account.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()
125 141
                          //Trim the account name
126
                          select Path.Combine(accountPath, "others-shared", relativePath)).ToList();
142
                          select Path.Combine(accountPath, FolderConstants.OthersFolder, relativePath)).ToList();
127 143
            return own.Union(others).ToList();
128 144
        }
129 145

  
b/trunk/Pithos.Core/Agents/SnapshotDifferencer.cs
184 184
            {
185 185
                return Common.Where(info => 
186 186
                    //The hash is different
187
                    info.PreviousHash != info.Hash 
187
                    info.PreviousHash != info.X_Object_Hash 
188 188
                    //And the Uri is unchanged or there is no previous version
189 189
                    && (info.Previous == null ||  info.Uri == info.Previous.Uri));
190 190
            }
......
195 195
        /// </summary>
196 196
        public IEnumerable<ObjectInfo> Unchanged
197 197
        {
198
            get{ return Common.Where(i => i.PreviousHash == i.Hash);}
198
            get { return Common.Where(i => i.PreviousHash == i.X_Object_Hash); }
199 199
        }
200 200

  
201 201
        /// <summary>
b/trunk/Pithos.Core/Agents/StatusAgent.cs
672 672
                    }
673 673

  
674 674
                    command.Parameters.AddWithValue("path", path);
675
                    command.Parameters.AddWithValue("checksum", objectInfo.Hash);
676
                    command.Parameters.AddWithValue("shortHash", "");
675
                    command.Parameters.AddWithValue("checksum", objectInfo.X_Object_Hash);
676
                    command.Parameters.AddWithValue("shortHash", objectInfo.ETag);
677 677
                    command.Parameters.AddWithValue("version", objectInfo.Version);
678 678
                    command.Parameters.AddWithValue("versionTimeStamp", objectInfo.VersionTimestamp);
679 679
                    command.Parameters.AddWithValue("fileStatus", FileStatus.Unchanged);
b/trunk/Pithos.Core/Agents/Uploader.cs
134 134
                            if (fileInfo is DirectoryInfo)
135 135
                            {
136 136
                                //If the directory doesn't exist the Hash property will be empty
137
                                if (String.IsNullOrWhiteSpace(cloudInfo.Hash))
137
                                if (String.IsNullOrWhiteSpace(cloudInfo.X_Object_Hash))
138 138
                                    //Go on and create the directory
139 139
                                    await client.PutObject(account, cloudFile.Container, cloudFile.Name, fullFileName,
140 140
                                                         String.Empty, "application/directory");
......
142 142
                                if (action.IsCreation)
143 143
                                {
144 144
                                    //Add the folder to the Selected URls
145
                                    var selections = Selectives.SelectiveUris[accountInfo.AccountKey];
146 145
                                    var selectiveUri = new Uri(client.RootAddressUri, cloudFile.Uri);
147
                                    selections.Add(selectiveUri);
146
                                    Selectives.AddUri(accountInfo, selectiveUri);                                    
148 147
                                    Selectives.Save(accountInfo);
149 148
                                }
150 149
                            }
151 150
                            else
152 151
                            {
153 152

  
154
                                var cloudHash = cloudInfo.Hash.ToLower();
153
                                var cloudHash = cloudInfo.X_Object_Hash.ToLower();
155 154

  
156 155
                                string topHash;
157 156
                                TreeHash treeHash;
b/trunk/Pithos.Core/LocalFileComparer.cs
14 14
                return false;
15 15
            if (x.CloudFile != null && y.CloudFile != null )
16 16
            {
17
                if (x.CloudFile.Hash == null & y.CloudFile.Hash != null)
17
                if (x.CloudFile.X_Object_Hash == null & y.CloudFile.X_Object_Hash != null)
18 18
                    return false;
19
                if (x.CloudFile.Hash != null & y.CloudFile.Hash == null)
19
                if (x.CloudFile.X_Object_Hash != null & y.CloudFile.X_Object_Hash == null)
20 20
                    return false;
21
                if (x.CloudFile.Hash == null & y.CloudFile.Hash == null)
21
                if (x.CloudFile.X_Object_Hash == null & y.CloudFile.X_Object_Hash == null)
22 22
                    return (x.CloudFile.Name == y.CloudFile.Name);
23
                    
24
                if (!x.CloudFile.Hash.Equals(y.CloudFile.Hash))
23

  
24
                if (!x.CloudFile.X_Object_Hash.Equals(y.CloudFile.X_Object_Hash))
25 25
                    return false;
26 26
                //All directories have the same hash. Compare them using their names instead
27 27
                if (x.CloudFile.Content_Type == y.CloudFile.Content_Type && x.CloudFile.IsDirectory)
......
45 45
            {
46 46
                //All directories have the same hash code. Use their name's hash code instead
47 47
                hash2 = obj.CloudFile.IsDirectory 
48
                            ? obj.CloudFile.Name.GetHashCode() 
49
                            : (obj.CloudFile.Hash ?? obj.CloudFile.Name ?? "").GetHashCode();
48
                            ? obj.CloudFile.Name.GetHashCode()
49
                            : (obj.CloudFile.X_Object_Hash ?? obj.CloudFile.Name ?? "").GetHashCode();
50 50
            }
51 51
            var hash3 = obj.Action.GetHashCode();
52 52
            return hash1 ^ hash2 & hash3;
b/trunk/Pithos.Interfaces/ObjectInfo.cs
58 58
        private readonly List<string> _knownContainers= new List<string>{"trash"};
59 59
        public string Name { get; set; }
60 60

  
61
        [JsonProperty("hash")]
61 62
        public string ETag { get; set; }
62 63

  
63
        public string Hash { get; set; }
64
        //public string Hash { get; set; }
64 65

  
66
/*
65 67
        public string X_Object_Hash { get { return Hash; } set { Hash = value; } }
68
*/
69

  
70
        public string X_Object_Hash { get; set; }
66 71

  
67 72
        [JsonProperty("x_object_uuid")]
68 73
        public string UUID { get; set; }
......
234 239
        public static ObjectInfo Empty = new ObjectInfo
235 240
        {
236 241
            Name = String.Empty,
237
            Hash = String.Empty,
242
            ETag= String.Empty,
243
            X_Object_Hash= String.Empty,
238 244
            Bytes = 0,
239 245
            Content_Type = String.Empty,
240 246
            Last_Modified = DateTime.MinValue,
......
373 379
        public ObjectInfo SetPrevious(ObjectInfo previous)
374 380
        {            
375 381
            Previous = previous;
376
            PreviousHash = previous.Hash;
382
            PreviousHash = previous.X_Object_Hash;
377 383
            return this;
378 384
        }
379 385

  
b/trunk/Pithos.Network.Test/ChecksumTest.cs
41 41

  
42 42

  
43 43
                    var meta = client.GetObjectInfo(null, "Shares", "DeveloperGuide.pdf");
44
                    Assert.IsNotEmpty(meta.Hash);
45
                    
44
                    Assert.IsNotEmpty(meta.X_Object_Hash);
45

  
46 46

  
47
                    Assert.AreEqual(hash,meta.Hash,String.Format("The hashes don't match, expected {0} but got {1}",hash,meta.Hash));
47
                    Assert.AreEqual(hash, meta.X_Object_Hash, String.Format("The hashes don't match, expected {0} but got {1}", hash, meta.X_Object_Hash));
48 48
                
49 49

  
50 50
            });
b/trunk/Pithos.Network.Test/NetworkOpsTest.cs
189 189

  
190 190
                
191 191
                var meta=client.GetObjectInfo(null, "Shares", filePath);
192
                Assert.IsNotEmpty(meta.Hash);
192
                Assert.IsNotEmpty(meta.X_Object_Hash);
193 193
                Assert.AreEqual(meta.Name,filePath);
194 194

  
195 195
            });
b/trunk/Pithos.Network/AccountInfo.cs
92 92
        }
93 93

  
94 94
        public List<Group> Groups { get; set; }
95

  
95 96
    }
96 97

  
97 98
    public class Group

Also available in: Unified diff