Revision c945b450 trunk/Pithos.Core/Agents/FileAgent.cs
b/trunk/Pithos.Core/Agents/FileAgent.cs | ||
---|---|---|
57 | 57 |
{ |
58 | 58 |
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
59 | 59 |
|
60 |
Agent<WorkflowState> _agent; |
|
60 |
/* |
|
61 |
Agent<WorkflowState> _agent; |
|
62 |
*/ |
|
61 | 63 |
private FileSystemWatcher _watcher; |
62 | 64 |
private FileSystemWatcherAdapter _adapter; |
65 |
private FileEventIdleBatch _eventIdleBatch; |
|
63 | 66 |
|
64 | 67 |
//[Import] |
65 | 68 |
public IStatusKeeper StatusKeeper { get; set; } |
... | ... | |
68 | 71 |
//[Import] |
69 | 72 |
public IPithosWorkflow Workflow { get; set; } |
70 | 73 |
//[Import] |
71 |
public WorkflowAgent WorkflowAgent { get; set; } |
|
74 |
//public WorkflowAgent WorkflowAgent { get; set; }
|
|
72 | 75 |
|
73 | 76 |
private AccountInfo AccountInfo { get; set; } |
74 | 77 |
|
75 | 78 |
internal string RootPath { get; set; } |
76 | 79 |
|
77 |
private FileEventIdleBatch _eventIdleBatch; |
|
78 |
|
|
79 | 80 |
public TimeSpan IdleTimeout { get; set; } |
80 | 81 |
|
82 |
public PollAgent PollAgent { get; set; } |
|
81 | 83 |
|
82 | 84 |
private void ProcessBatchedEvents(Dictionary<string, FileSystemEventArgs[]> fileEvents) |
83 | 85 |
{ |
86 |
PollAgent.SynchNow(); |
|
87 |
} |
|
88 |
|
|
89 |
/* |
|
90 |
private void ProcessBatchedEvents(Dictionary<string, FileSystemEventArgs[]> fileEvents) |
|
91 |
{ |
|
84 | 92 |
StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,String.Format("Uploading {0} files",fileEvents.Count)); |
85 | 93 |
//Start with events that do not originate in one of the ignored folders |
86 | 94 |
var initialEvents = from evt in fileEvents |
... | ... | |
156 | 164 |
} |
157 | 165 |
StatusNotification.SetPithosStatus(PithosStatus.LocalComplete); |
158 | 166 |
} |
167 |
*/ |
|
159 | 168 |
|
160 | 169 |
public void Start(AccountInfo accountInfo,string rootPath) |
161 | 170 |
{ |
... | ... | |
167 | 176 |
throw new ArgumentException("rootPath must be an absolute path","rootPath"); |
168 | 177 |
if (IdleTimeout == null) |
169 | 178 |
throw new InvalidOperationException("IdleTimeout must have a valid value"); |
170 |
Contract.EndContractBlock(); |
|
179 |
Contract.EndContractBlock();
|
|
171 | 180 |
|
172 | 181 |
AccountInfo = accountInfo; |
173 | 182 |
RootPath = rootPath; |
174 |
|
|
183 |
|
|
175 | 184 |
_eventIdleBatch = new FileEventIdleBatch((int)IdleTimeout.TotalMilliseconds, ProcessBatchedEvents); |
176 | 185 |
|
177 |
_watcher = new FileSystemWatcher(rootPath) {IncludeSubdirectories = true,InternalBufferSize=8*4096};
|
|
186 |
_watcher = new FileSystemWatcher(rootPath) { IncludeSubdirectories = true, InternalBufferSize = 8 * 4096 };
|
|
178 | 187 |
_adapter = new FileSystemWatcherAdapter(_watcher); |
179 | 188 |
|
180 | 189 |
_adapter.Changed += OnFileEvent; |
... | ... | |
184 | 193 |
_adapter.Moved += OnMoveEvent; |
185 | 194 |
_watcher.EnableRaisingEvents = true; |
186 | 195 |
|
196 |
/* |
|
197 |
|
|
198 |
|
|
187 | 199 |
|
188 | 200 |
_agent = Agent<WorkflowState>.Start(inbox => |
189 | 201 |
{ |
... | ... | |
196 | 208 |
Log.ErrorFormat("[ERROR] File Event Processing:\r{0}", ex)); |
197 | 209 |
}; |
198 | 210 |
loop(); |
199 |
}); |
|
211 |
});*/
|
|
200 | 212 |
} |
201 | 213 |
|
214 |
/* |
|
202 | 215 |
private Task<object> Process(WorkflowState state) |
203 | 216 |
{ |
204 | 217 |
if (state==null) |
... | ... | |
256 | 269 |
_watcher.EnableRaisingEvents = !value; |
257 | 270 |
} |
258 | 271 |
} |
272 |
*/ |
|
259 | 273 |
|
260 | 274 |
public string CachePath { get; set; } |
261 | 275 |
|
... | ... | |
269 | 283 |
public Selectives Selectives { get; set; } |
270 | 284 |
|
271 | 285 |
|
286 |
/* |
|
272 | 287 |
public void Post(WorkflowState workflowState) |
273 | 288 |
{ |
274 | 289 |
if (workflowState == null) |
... | ... | |
290 | 305 |
_agent.Stop(); |
291 | 306 |
} |
292 | 307 |
|
308 |
*/ |
|
293 | 309 |
// Enumerate all files in the Pithos directory except those in the Fragment folder |
294 | 310 |
// and files with a .ignore extension |
295 | 311 |
public IEnumerable<string> EnumerateFiles(string searchPattern="*") |
296 | 312 |
{ |
297 | 313 |
var monitoredFiles = from filePath in Directory.EnumerateFileSystemEntries(RootPath, searchPattern, SearchOption.AllDirectories) |
298 | 314 |
where !Ignore(filePath) |
315 |
orderby filePath ascending |
|
299 | 316 |
select filePath; |
300 | 317 |
return monitoredFiles; |
301 | 318 |
} |
... | ... | |
305 | 322 |
var rootDir = new DirectoryInfo(RootPath); |
306 | 323 |
var monitoredFiles = from file in rootDir.EnumerateFiles(searchPattern, SearchOption.AllDirectories) |
307 | 324 |
where !Ignore(file.FullName) |
325 |
orderby file.FullName ascending |
|
308 | 326 |
select file; |
309 | 327 |
return monitoredFiles; |
310 | 328 |
} |
311 | 329 |
|
330 |
public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(string searchPattern="*") |
|
331 |
{ |
|
332 |
var rootDir = new DirectoryInfo(RootPath); |
|
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) |
|
338 |
//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); |
|
343 |
return monitoredFiles; |
|
344 |
} |
|
345 |
|
|
312 | 346 |
public IEnumerable<string> EnumerateFilesAsRelativeUrls(string searchPattern="*") |
313 | 347 |
{ |
314 | 348 |
var rootDir = new DirectoryInfo(RootPath); |
315 | 349 |
var monitoredFiles = from file in rootDir.EnumerateFiles(searchPattern, SearchOption.AllDirectories) |
316 | 350 |
where !Ignore(file.FullName) |
351 |
orderby file.FullName ascending |
|
317 | 352 |
select file.AsRelativeUrlTo(RootPath); |
318 | 353 |
return monitoredFiles; |
319 | 354 |
} |
... | ... | |
323 | 358 |
var rootDir = new DirectoryInfo(RootPath); |
324 | 359 |
var monitoredFiles = from file in rootDir.EnumerateFileSystemInfos(searchPattern, SearchOption.AllDirectories) |
325 | 360 |
where !Ignore(file.FullName) |
361 |
orderby file.FullName ascending |
|
326 | 362 |
select file.AsRelativeUrlTo(RootPath); |
327 | 363 |
return monitoredFiles; |
328 | 364 |
} |
... | ... | |
330 | 366 |
|
331 | 367 |
|
332 | 368 |
|
333 |
private bool Ignore(string filePath)
|
|
369 |
public bool Ignore(string filePath)
|
|
334 | 370 |
{ |
335 | 371 |
if (IgnorePaths(filePath)) return true; |
336 | 372 |
|
337 | 373 |
|
338 | 374 |
//If selective sync is enabled, |
339 |
if (Selectives.IsSelectiveEnabled(AccountInfo.AccountKey) |
|
340 |
//propagate folder events |
|
341 |
&& Directory.Exists(filePath) |
|
342 |
//from the container root folder only. Note, in the first level below the account root path are the containers |
|
343 |
&& FoundBelowRoot(filePath, RootPath, 2)) |
|
375 |
if (IsUnselectedRootFolder(filePath)) |
|
344 | 376 |
return false; |
345 | 377 |
//Ignore if selective synchronization is defined, |
346 | 378 |
//And the target file is not below any of the selective paths |
347 | 379 |
return !Selectives.IsSelected(AccountInfo, filePath); |
348 | 380 |
} |
349 | 381 |
|
350 |
private bool IgnorePaths(string filePath) |
|
382 |
public bool IsUnselectedRootFolder(string filePath) |
|
383 |
{ |
|
384 |
return Selectives.IsSelectiveEnabled(AccountInfo.AccountKey) //propagate folder events |
|
385 |
&& Directory.Exists(filePath) //from the container root folder only. Note, in the first level below the account root path are the containers |
|
386 |
&& FoundBelowRoot(filePath, RootPath, 2); |
|
387 |
} |
|
388 |
|
|
389 |
public bool IgnorePaths(string filePath) |
|
351 | 390 |
{ |
352 | 391 |
//Ignore all first-level directories and files (ie at the container folders level) |
353 | 392 |
if (FoundBelowRoot(filePath, RootPath, 1)) |
... | ... | |
415 | 454 |
return false; |
416 | 455 |
} |
417 | 456 |
|
418 |
//Post a Change message for all events except rename |
|
419 |
void OnFileEvent(object sender, FileSystemEventArgs e) |
|
420 |
{ |
|
421 |
//Ignore events that affect the cache folder |
|
422 |
var filePath = e.FullPath; |
|
423 |
if (Ignore(filePath)) |
|
424 |
return; |
|
425 |
_eventIdleBatch.Post(e); |
|
426 |
} |
|
427 |
|
|
428 |
|
|
429 |
/* |
|
457 |
/* |
|
430 | 458 |
//Post a Change message for renames containing the old and new names |
431 | 459 |
void OnRenameEvent(object sender, RenamedEventArgs e) |
432 | 460 |
{ |
... | ... | |
445 | 473 |
TriggeringChange = e.ChangeType |
446 | 474 |
}); |
447 | 475 |
} |
448 |
*/ |
|
476 |
*/ |
|
477 |
|
|
478 |
//Post a Change message for all events except rename |
|
479 |
void OnFileEvent(object sender, FileSystemEventArgs e) |
|
480 |
{ |
|
481 |
//Ignore events that affect the cache folder |
|
482 |
var filePath = e.FullPath; |
|
483 |
if (Ignore(filePath)) |
|
484 |
return; |
|
485 |
_eventIdleBatch.Post(e); |
|
486 |
} |
|
449 | 487 |
|
450 | 488 |
//Post a Change message for moves containing the old and new names |
451 | 489 |
void OnMoveEvent(object sender, MovedEventArgs e) |
Also available in: Unified diff