Revision 9a1c7fda trunk/Pithos.Core/Agents/FileAgent.cs
b/trunk/Pithos.Core/Agents/FileAgent.cs | ||
---|---|---|
100 | 100 |
PollAgent.SynchNow(paths); |
101 | 101 |
} |
102 | 102 |
|
103 |
/* |
|
104 |
private void ProcessBatchedEvents(Dictionary<string, FileSystemEventArgs[]> fileEvents) |
|
105 |
{ |
|
106 |
StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,String.Format("Uploading {0} files",fileEvents.Count)); |
|
107 |
//Start with events that do not originate in one of the ignored folders |
|
108 |
var initialEvents = from evt in fileEvents |
|
109 |
where !IgnorePaths(evt.Key) |
|
110 |
select evt; |
|
111 |
|
|
112 |
IEnumerable<KeyValuePair<string, FileSystemEventArgs[]>> cleanEvents; |
|
113 |
|
|
114 |
|
|
115 |
var selectiveEnabled = Selectives.IsSelectiveEnabled(AccountInfo.AccountKey); |
|
116 |
//When selective sync is enabled, |
|
117 |
if (selectiveEnabled) |
|
118 |
{ |
|
119 |
//Include all selected items |
|
120 |
var selectedEvents = from evt in initialEvents |
|
121 |
where Selectives.IsSelected(AccountInfo, evt.Key) |
|
122 |
select evt; |
|
123 |
//And all folder creations in the unselected folders |
|
124 |
var folderCreations = from evt in initialEvents |
|
125 |
let folderPath=evt.Key |
|
126 |
//The original folder may not exist due to renames. Just make sure that the path is not a file |
|
127 |
where !File.Exists(folderPath) |
|
128 |
//We only want unselected items |
|
129 |
&& !Selectives.IsSelected(AccountInfo, folderPath) |
|
130 |
//Is there any creation event related to the folder? |
|
131 |
&& evt.Value.Any(arg => arg.ChangeType == WatcherChangeTypes.Created) |
|
132 |
select evt; |
|
133 |
cleanEvents = selectedEvents.Union(folderCreations).ToList(); |
|
134 |
} |
|
135 |
//If selective is disabled, only exclude the shared folders |
|
136 |
else |
|
137 |
{ |
|
138 |
cleanEvents = (from evt in initialEvents |
|
139 |
where !evt.Key.IsSharedTo(AccountInfo) |
|
140 |
select evt).ToList(); |
|
141 |
} |
|
142 |
|
|
143 |
|
|
144 |
foreach (var fileEvent in cleanEvents) |
|
145 |
{ |
|
146 |
//var filePath = fileEvent.Key; |
|
147 |
var changes = fileEvent.Value; |
|
148 |
|
|
149 |
var isNotFile = !File.Exists(fileEvent.Key); |
|
150 |
foreach (var change in changes) |
|
151 |
{ |
|
152 |
if (change.ChangeType == WatcherChangeTypes.Renamed) |
|
153 |
{ |
|
154 |
var rename = (MovedEventArgs) change; |
|
155 |
_agent.Post(new WorkflowState(change) |
|
156 |
{ |
|
157 |
AccountInfo = AccountInfo, |
|
158 |
OldPath = rename.OldFullPath, |
|
159 |
OldFileName = Path.GetFileName(rename.OldName), |
|
160 |
Path = rename.FullPath, |
|
161 |
FileName = Path.GetFileName(rename.Name), |
|
162 |
TriggeringChange = rename.ChangeType |
|
163 |
}); |
|
164 |
} |
|
165 |
else |
|
166 |
{ |
|
167 |
var isCreation = selectiveEnabled && isNotFile && change.ChangeType == WatcherChangeTypes.Created; |
|
168 |
_agent.Post(new WorkflowState(change) |
|
169 |
{ |
|
170 |
AccountInfo = AccountInfo, |
|
171 |
Path = change.FullPath, |
|
172 |
FileName = Path.GetFileName(change.Name), |
|
173 |
TriggeringChange = change.ChangeType, |
|
174 |
IsCreation=isCreation |
|
175 |
}); |
|
176 |
} |
|
177 |
} |
|
178 |
} |
|
179 |
StatusNotification.SetPithosStatus(PithosStatus.LocalComplete); |
|
180 |
} |
|
181 |
*/ |
|
182 |
|
|
183 | 103 |
public void Start(AccountInfo accountInfo,string rootPath) |
184 | 104 |
{ |
185 | 105 |
if (accountInfo==null) |
... | ... | |
207 | 127 |
_adapter.Moved += OnMoveEvent; |
208 | 128 |
_watcher.EnableRaisingEvents = true; |
209 | 129 |
|
210 |
/* |
|
211 |
|
|
212 |
|
|
213 |
|
|
214 |
_agent = Agent<WorkflowState>.Start(inbox => |
|
215 |
{ |
|
216 |
Action loop = null; |
|
217 |
loop = () => |
|
218 |
{ |
|
219 |
var message = inbox.Receive(); |
|
220 |
var process=message.Then(Process,inbox.CancellationToken); |
|
221 |
inbox.LoopAsync(process,loop,ex=> |
|
222 |
Log.ErrorFormat("[ERROR] File Event Processing:\r{0}", ex)); |
|
223 |
}; |
|
224 |
loop(); |
|
225 |
});*/ |
|
226 | 130 |
} |
227 | 131 |
|
228 |
/* |
|
229 |
private Task<object> Process(WorkflowState state) |
|
230 |
{ |
|
231 |
if (state==null) |
|
232 |
throw new ArgumentNullException("state"); |
|
233 |
Contract.EndContractBlock(); |
|
234 |
|
|
235 |
if (Ignore(state.Path)) |
|
236 |
return CompletedTask<object>.Default; |
|
237 |
|
|
238 |
var networkState = NetworkGate.GetNetworkState(state.Path); |
|
239 |
//Skip if the file is already being downloaded or uploaded and |
|
240 |
//the change is create or modify |
|
241 |
if (networkState != NetworkOperation.None && |
|
242 |
( |
|
243 |
state.TriggeringChange == WatcherChangeTypes.Created || |
|
244 |
state.TriggeringChange == WatcherChangeTypes.Changed |
|
245 |
)) |
|
246 |
return CompletedTask<object>.Default; |
|
247 |
|
|
248 |
try |
|
249 |
{ |
|
250 |
//StatusKeeper.EnsureFileState(state.Path); |
|
251 |
|
|
252 |
UpdateFileStatus(state); |
|
253 |
UpdateOverlayStatus(state); |
|
254 |
UpdateLastMD5(state); |
|
255 |
WorkflowAgent.Post(state); |
|
256 |
} |
|
257 |
catch (IOException exc) |
|
258 |
{ |
|
259 |
if (File.Exists(state.Path)) |
|
260 |
{ |
|
261 |
Log.WarnFormat("File access error occured, retrying {0}\n{1}", state.Path, exc); |
|
262 |
_agent.Post(state); |
|
263 |
} |
|
264 |
else |
|
265 |
{ |
|
266 |
Log.WarnFormat("File {0} does not exist. Will be ignored\n{1}", state.Path, exc); |
|
267 |
} |
|
268 |
} |
|
269 |
catch (Exception exc) |
|
270 |
{ |
|
271 |
Log.WarnFormat("Error occured while indexing{0}. The file will be skipped\n{1}", |
|
272 |
state.Path, exc); |
|
273 |
} |
|
274 |
return CompletedTask<object>.Default; |
|
275 |
} |
|
276 |
|
|
277 |
public bool Pause |
|
278 |
{ |
|
279 |
get { return _watcher == null || !_watcher.EnableRaisingEvents; } |
|
280 |
set |
|
281 |
{ |
|
282 |
if (_watcher != null) |
|
283 |
_watcher.EnableRaisingEvents = !value; |
|
284 |
} |
|
285 |
} |
|
286 |
*/ |
|
287 | 132 |
|
288 | 133 |
public string CachePath { get; set; } |
289 | 134 |
|
290 |
/*private List<string> _selectivePaths = new List<string>(); |
|
291 |
public List<string> SelectivePaths |
|
292 |
{ |
|
293 |
get { return _selectivePaths; } |
|
294 |
set { _selectivePaths = value; } |
|
295 |
} |
|
296 |
*/ |
|
297 | 135 |
public Selectives Selectives { get; set; } |
298 | 136 |
|
299 |
|
|
300 |
/* |
|
301 |
public void Post(WorkflowState workflowState) |
|
302 |
{ |
|
303 |
if (workflowState == null) |
|
304 |
throw new ArgumentNullException("workflowState"); |
|
305 |
Contract.EndContractBlock(); |
|
306 |
|
|
307 |
_agent.Post(workflowState); |
|
308 |
} |
|
309 |
|
|
310 |
public void Stop() |
|
311 |
{ |
|
312 |
if (_watcher != null) |
|
313 |
{ |
|
314 |
_watcher.Dispose(); |
|
315 |
} |
|
316 |
_watcher = null; |
|
317 |
|
|
318 |
if (_agent!=null) |
|
319 |
_agent.Stop(); |
|
320 |
} |
|
321 |
|
|
322 |
*/ |
|
323 | 137 |
// Enumerate all files in the Pithos directory except those in the Fragment folder |
324 | 138 |
// and files with a .ignore extension |
325 | 139 |
public IEnumerable<string> EnumerateFiles(string searchPattern="*") |
... | ... | |
427 | 241 |
return _ignoreFiles.ContainsKey(filePath.ToLower()); |
428 | 242 |
} |
429 | 243 |
|
430 |
/* private static bool FoundInRoot(string filePath, string rootPath) |
|
431 |
{ |
|
432 |
//var rootDirectory = new DirectoryInfo(rootPath); |
|
433 |
|
|
434 |
//If the paths are equal, return true |
|
435 |
if (filePath.Equals(rootPath, StringComparison.InvariantCultureIgnoreCase)) |
|
436 |
return true; |
|
437 |
|
|
438 |
//If the filepath is below the root path |
|
439 |
if (filePath.StartsWith(rootPath,StringComparison.InvariantCulture)) |
|
440 |
{ |
|
441 |
//Get the relative path |
|
442 |
var relativePath = filePath.Substring(rootPath.Length + 1); |
|
443 |
//If the relativePath does NOT contains a path separator, we found a match |
|
444 |
return (!relativePath.Contains(@"\")); |
|
445 |
} |
|
446 |
|
|
447 |
//If the filepath is not under the root path, return false |
|
448 |
return false; |
|
449 |
}*/ |
|
450 |
|
|
451 | 244 |
|
452 | 245 |
private static bool FoundBelowRoot(string filePath, string rootPath,int level) |
453 | 246 |
{ |
... | ... | |
471 | 264 |
return false; |
472 | 265 |
} |
473 | 266 |
|
474 |
/* |
|
475 |
//Post a Change message for renames containing the old and new names |
|
476 |
void OnRenameEvent(object sender, RenamedEventArgs e) |
|
477 |
{ |
|
478 |
var oldFullPath = e.OldFullPath; |
|
479 |
var fullPath = e.FullPath; |
|
480 |
if (Ignore(oldFullPath) || Ignore(fullPath)) |
|
481 |
return; |
|
482 |
|
|
483 |
_agent.Post(new WorkflowState |
|
484 |
{ |
|
485 |
AccountInfo=AccountInfo, |
|
486 |
OldPath = oldFullPath, |
|
487 |
OldFileName = e.OldName, |
|
488 |
Path = fullPath, |
|
489 |
FileName = e.Name, |
|
490 |
TriggeringChange = e.ChangeType |
|
491 |
}); |
|
492 |
} |
|
493 |
*/ |
|
494 | 267 |
|
495 | 268 |
//Post a Change message for all events except rename |
496 | 269 |
void OnFileEvent(object sender, FileSystemEventArgs e) |
... | ... | |
557 | 330 |
return state; |
558 | 331 |
} |
559 | 332 |
|
560 |
/* private WorkflowState UpdateOverlayStatus(WorkflowState state) |
|
561 |
{ |
|
562 |
if (state==null) |
|
563 |
throw new ArgumentNullException("state"); |
|
564 |
Contract.EndContractBlock(); |
|
565 |
|
|
566 |
if (state.Skip) |
|
567 |
return state; |
|
568 |
|
|
569 |
switch (state.Status) |
|
570 |
{ |
|
571 |
case FileStatus.Created: |
|
572 |
this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified,state.ETag).Wait(); |
|
573 |
break; |
|
574 |
case FileStatus.Modified: |
|
575 |
this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified, state.ETag).Wait(); |
|
576 |
break; |
|
577 |
case FileStatus.Deleted: |
|
578 |
//this.StatusAgent.RemoveFileOverlayStatus(state.Path); |
|
579 |
break; |
|
580 |
case FileStatus.Renamed: |
|
581 |
this.StatusKeeper.ClearFileStatus(state.OldPath); |
|
582 |
this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified, state.ETag).Wait(); |
|
583 |
break; |
|
584 |
case FileStatus.Unchanged: |
|
585 |
this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Normal, state.ETag).Wait(); |
|
586 |
break; |
|
587 |
} |
|
588 |
|
|
589 |
if (state.Status == FileStatus.Deleted) |
|
590 |
NativeMethods.RaiseChangeNotification(Path.GetDirectoryName(state.Path)); |
|
591 |
else |
|
592 |
NativeMethods.RaiseChangeNotification(state.Path); |
|
593 |
return state; |
|
594 |
} |
|
595 |
|
|
596 |
|
|
597 |
private WorkflowState UpdateFileChecksum(WorkflowState state) |
|
598 |
{ |
|
599 |
if (state.Skip) |
|
600 |
return state; |
|
601 |
|
|
602 |
if (state.Status == FileStatus.Deleted) |
|
603 |
return state; |
|
604 |
|
|
605 |
var path = state.Path; |
|
606 |
//Skip calculation for folders |
|
607 |
if (Directory.Exists(path)) |
|
608 |
return state; |
|
609 |
|
|
610 |
var info = new FileInfo(path); |
|
611 |
|
|
612 |
using (StatusNotification.GetNotifier("Hashing {0}", "Finished Hashing {0}", info.Name)) |
|
613 |
{ |
|
614 |
|
|
615 |
var etag = info.ComputeShortHash(StatusNotification); |
|
616 |
|
|
617 |
var progress = new Progress<double>(d => |
|
618 |
StatusNotification.Notify(new StatusNotification(String.Format("Hashing {0} of {1}", d, info.Name)))); |
|
619 |
|
|
620 |
string merkleHash = info.CalculateHash(StatusKeeper.BlockSize, StatusKeeper.BlockHash,PollAgent.CancellationToken,progress); |
|
621 |
StatusKeeper.UpdateFileChecksum(path, etag, merkleHash); |
|
622 |
|
|
623 |
state.Hash = merkleHash; |
|
624 |
return state; |
|
625 |
} |
|
626 |
}*/ |
|
627 |
|
|
333 |
|
|
628 | 334 |
//Does the file exist in the container's local folder? |
629 | 335 |
public bool Exists(string relativePath) |
630 | 336 |
{ |
Also available in: Unified diff