2 using System.Collections.Generic;
3 using System.ComponentModel.Composition;
4 using System.Diagnostics;
8 using Pithos.Interfaces;
10 namespace Pithos.Core.Agents
13 public class FileWatcherAgent
15 Agent<WorkflowState> _agent;
16 private FileSystemWatcher _watcher;
19 public IStatusKeeper StatusKeeper { get; set; }
21 public IPithosWorkflow Workflow { get; set; }
23 public WorkflowAgent WorkflowAgent { get; set; }
25 public void Start(string path)
27 _watcher = new FileSystemWatcher(path);
28 _watcher.Changed += OnFileEvent;
29 _watcher.Created += OnFileEvent;
30 _watcher.Deleted += OnFileEvent;
31 _watcher.Renamed += OnRenameEvent;
32 _watcher.EnableRaisingEvents = true;
35 _agent = Agent<WorkflowState>.Start(inbox =>
40 var message = inbox.Receive();
41 var process = message.ContinueWith(t =>
48 process.ContinueWith(t =>
53 var ex = t.Exception.InnerException;
54 if (ex is OperationCanceledException)
56 Trace.TraceError("[ERROR] File Event Processing:\r{0}", ex);
67 get { return _watcher == null || !_watcher.EnableRaisingEvents; }
71 _watcher.EnableRaisingEvents = !value;
75 public void Post(WorkflowState workflowState)
77 _agent.Post(workflowState);
84 _watcher.Changed -= OnFileEvent;
85 _watcher.Created -= OnFileEvent;
86 _watcher.Deleted -= OnFileEvent;
87 _watcher.Renamed -= OnRenameEvent;
95 void OnFileEvent(object sender, FileSystemEventArgs e)
97 _agent.Post(new WorkflowState { Path = e.FullPath, FileName = e.Name, TriggeringChange = e.ChangeType });
100 void OnRenameEvent(object sender, RenamedEventArgs e)
102 _agent.Post(new WorkflowState
104 OldPath = e.OldFullPath,
105 OldFileName = e.OldName,
108 TriggeringChange = e.ChangeType
113 private void Process(WorkflowState state)
115 var networkState = StatusKeeper.GetNetworkState(state.Path);
116 //Skip if the file is already being downloaded or uploaded and
117 //the change is create or modify
118 if (networkState != NetworkState.None &&
120 state.TriggeringChange == WatcherChangeTypes.Created ||
121 state.TriggeringChange == WatcherChangeTypes.Changed
124 UpdateFileStatus(state);
125 UpdateOverlayStatus(state);
126 UpdateFileChecksum(state);
127 WorkflowAgent.Post(state);
130 private Dictionary<WatcherChangeTypes, FileStatus> _statusDict = new Dictionary<WatcherChangeTypes, FileStatus>
132 {WatcherChangeTypes.Created,FileStatus.Created},
133 {WatcherChangeTypes.Changed,FileStatus.Modified},
134 {WatcherChangeTypes.Deleted,FileStatus.Deleted},
135 {WatcherChangeTypes.Renamed,FileStatus.Renamed}
138 private WorkflowState UpdateFileStatus(WorkflowState state)
140 string path = state.Path;
141 FileStatus status = _statusDict[state.TriggeringChange];
142 var oldStatus = Workflow.StatusKeeper.GetFileStatus(path);
143 if (status == oldStatus)
145 state.Status = status;
149 if (state.Status == FileStatus.Renamed)
150 Workflow.ClearFileStatus(path);
152 state.Status = Workflow.SetFileStatus(path, status);
156 private WorkflowState UpdateOverlayStatus(WorkflowState state)
161 switch (state.Status)
163 case FileStatus.Created:
164 case FileStatus.Modified:
165 this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified);
167 case FileStatus.Deleted:
168 this.StatusKeeper.RemoveFileOverlayStatus(state.Path);
170 case FileStatus.Renamed:
171 this.StatusKeeper.RemoveFileOverlayStatus(state.OldPath);
172 this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified);
174 case FileStatus.Unchanged:
175 this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Normal);
179 if (state.Status == FileStatus.Deleted)
180 Workflow.RaiseChangeNotification(Path.GetDirectoryName(state.Path));
182 Workflow.RaiseChangeNotification(state.Path);
187 private WorkflowState UpdateFileChecksum(WorkflowState state)
192 if (state.Status == FileStatus.Deleted)
195 string path = state.Path;
196 string hash = Signature.CalculateMD5(path);
198 StatusKeeper.UpdateFileChecksum(path, hash);