Revision badcef63 trunk/Pithos.Core/Agents/FileSystemWatcherAdapter.cs
b/trunk/Pithos.Core/Agents/FileSystemWatcherAdapter.cs | ||
---|---|---|
39 | 39 |
* ----------------------------------------------------------------------- |
40 | 40 |
*/ |
41 | 41 |
#endregion |
42 |
|
|
43 |
using System.Diagnostics; |
|
42 | 44 |
using System.Diagnostics.Contracts; |
43 | 45 |
using System.IO; |
44 | 46 |
using System.Reflection; |
... | ... | |
84 | 86 |
} |
85 | 87 |
|
86 | 88 |
private string _cachedDeletedFullPath; |
89 |
private string CachedDeletedFullPath |
|
90 |
{ |
|
91 |
get { return _cachedDeletedFullPath; } |
|
92 |
set |
|
93 |
{ |
|
94 |
Debug.Assert(Path.IsPathRooted(CachedDeletedFullPath)); |
|
95 |
if (!Path.IsPathRooted(CachedDeletedFullPath)) |
|
96 |
Log.WarnFormat("Storing a relative CachedDeletedFullPath: {0}",value); |
|
97 |
_cachedDeletedFullPath = value; |
|
98 |
} |
|
99 |
} |
|
100 |
|
|
101 |
/// <summary> |
|
102 |
/// Clears any cached deleted file path |
|
103 |
/// </summary> |
|
104 |
/// <remarks> |
|
105 |
/// This method was added to bypass the null checking in the property's setter |
|
106 |
/// </remarks> |
|
107 |
private void ClearCachedDeletedPath() |
|
108 |
{ |
|
109 |
_cachedDeletedFullPath = null; |
|
110 |
} |
|
111 |
|
|
112 |
|
|
87 | 113 |
private const int PropagateDelay = 10; |
88 | 114 |
|
89 | 115 |
private void OnDeleted(object sender, FileSystemEventArgs e) |
... | ... | |
115 | 141 |
//TODO: Moving a folder to the recycle bin results in a single delete event for the entire folder and its contents |
116 | 142 |
// as this is actually a MOVE operation |
117 | 143 |
//Deleting by Shift+Delete results in a delete event for each file followed by the delete of the folder itself |
118 |
_cachedDeletedFullPath = e.FullPath;
|
|
144 |
CachedDeletedFullPath = e.FullPath;
|
|
119 | 145 |
|
120 |
//TODO: This requires synchronization of the _cachedDeletedFullPath field
|
|
146 |
//TODO: This requires synchronization of the CachedDeletedFullPath field
|
|
121 | 147 |
//TODO: This creates a new task for each file even though we can cancel any existing tasks if a new event arrives |
122 | 148 |
//Maybe, use a timer instead of a task |
123 | 149 |
|
124 | 150 |
TaskEx.Delay(PropagateDelay).ContinueWith(t => |
125 | 151 |
{ |
126 | 152 |
var myPath = e.FullPath; |
127 |
if (_cachedDeletedFullPath == myPath)
|
|
153 |
if (CachedDeletedFullPath == myPath)
|
|
128 | 154 |
PropagateCachedDeleted(sender); |
129 | 155 |
}); |
130 | 156 |
} |
... | ... | |
184 | 210 |
} |
185 | 211 |
finally |
186 | 212 |
{ |
187 |
_cachedDeletedFullPath = null;
|
|
213 |
ClearCachedDeletedPath();
|
|
188 | 214 |
} |
189 | 215 |
} |
190 | 216 |
|
... | ... | |
225 | 251 |
finally |
226 | 252 |
{ |
227 | 253 |
//Finally, make sure the cached path is cleared |
228 |
_cachedDeletedFullPath = null;
|
|
254 |
ClearCachedDeletedPath();
|
|
229 | 255 |
} |
230 | 256 |
} |
231 | 257 |
|
258 |
|
|
232 | 259 |
private void RaiseCreatedForChildren(object sender, FileSystemEventArgs e) |
233 | 260 |
{ |
234 | 261 |
Contract.Requires(sender!=null); |
... | ... | |
269 | 296 |
//instead of a sequence of independent actions |
270 | 297 |
//One way to detect this would be to request that the full paths are NOT the same |
271 | 298 |
|
272 |
var oldName = Path.GetFileName(_cachedDeletedFullPath);
|
|
299 |
var oldName = Path.GetFileName(CachedDeletedFullPath);
|
|
273 | 300 |
//NOTE: e.Name is a path relative to the watched path. We MUST call Path.GetFileName to get the actual path |
274 | 301 |
var newName = Path.GetFileName(e.Name); |
275 | 302 |
//If the last deleted filename is equal to the current and the action is create, we have a MOVE operation |
276 |
var hasMoved = (_cachedDeletedFullPath != e.FullPath && oldName == newName);
|
|
303 |
var hasMoved = (CachedDeletedFullPath != e.FullPath && oldName == newName);
|
|
277 | 304 |
|
278 | 305 |
if (!hasMoved) |
279 | 306 |
return false; |
... | ... | |
285 | 312 |
|
286 | 313 |
//If the actual action is a Move, raise a Move event instead of the actual event |
287 | 314 |
var newDirectory = Path.GetDirectoryName(e.FullPath); |
288 |
var oldDirectory = Path.GetDirectoryName(_cachedDeletedFullPath);
|
|
315 |
var oldDirectory = Path.GetDirectoryName(CachedDeletedFullPath);
|
|
289 | 316 |
|
290 | 317 |
if (Moved != null) |
291 | 318 |
{ |
... | ... | |
313 | 340 |
} |
314 | 341 |
finally |
315 | 342 |
{ |
316 |
_cachedDeletedFullPath = null;
|
|
343 |
ClearCachedDeletedPath();
|
|
317 | 344 |
} |
318 | 345 |
return true; |
319 | 346 |
} |
... | ... | |
322 | 349 |
{ |
323 | 350 |
if (sender == null) |
324 | 351 |
throw new ArgumentNullException("sender"); |
325 |
Contract.Ensures(_cachedDeletedFullPath == null);
|
|
352 |
Contract.Ensures(CachedDeletedFullPath == null);
|
|
326 | 353 |
Contract.EndContractBlock(); |
327 | 354 |
|
328 | 355 |
//Nothing to handle if there is no cached deleted file |
329 |
if (String.IsNullOrWhiteSpace(_cachedDeletedFullPath))
|
|
356 |
if (String.IsNullOrWhiteSpace(CachedDeletedFullPath))
|
|
330 | 357 |
return; |
331 | 358 |
|
332 |
var deletedFileName = Path.GetFileName(_cachedDeletedFullPath);
|
|
333 |
var deletedFileDirectory = Path.GetDirectoryName(_cachedDeletedFullPath);
|
|
359 |
var deletedFileName = Path.GetFileName(CachedDeletedFullPath);
|
|
360 |
var deletedFileDirectory = Path.GetDirectoryName(CachedDeletedFullPath);
|
|
334 | 361 |
|
335 | 362 |
if (Log.IsDebugEnabled) |
336 |
Log.DebugFormat("Propagating delete for [{0}]", _cachedDeletedFullPath);
|
|
363 |
Log.DebugFormat("Propagating delete for [{0}]", CachedDeletedFullPath);
|
|
337 | 364 |
|
338 | 365 |
//Only a single file Delete event is raised when moving a file to the Recycle Bin, as this is actually a MOVE operation |
339 | 366 |
//In this case we need to raise the proper events for all child objects of the deleted directory. |
... | ... | |
342 | 369 |
if (Deleted != null) |
343 | 370 |
Deleted(sender,new FileSystemEventArgs(WatcherChangeTypes.Deleted, deletedFileDirectory, deletedFileName)); |
344 | 371 |
|
345 |
_cachedDeletedFullPath = null;
|
|
372 |
ClearCachedDeletedPath();
|
|
346 | 373 |
} |
347 | 374 |
} |
348 | 375 |
} |
Also available in: Unified diff