root / trunk / Pithos.Core / Agents / FileAgent.cs @ b666b39a
History | View | Annotate | Download (19.8 kB)
1 | 255f5f86 | Panagiotis Kanavos | #region |
---|---|---|---|
2 | 255f5f86 | Panagiotis Kanavos | /* ----------------------------------------------------------------------- |
3 | 255f5f86 | Panagiotis Kanavos | * <copyright file="FileAgent.cs" company="GRNet"> |
4 | 255f5f86 | Panagiotis Kanavos | * |
5 | 255f5f86 | Panagiotis Kanavos | * Copyright 2011-2012 GRNET S.A. All rights reserved. |
6 | 255f5f86 | Panagiotis Kanavos | * |
7 | 255f5f86 | Panagiotis Kanavos | * Redistribution and use in source and binary forms, with or |
8 | 255f5f86 | Panagiotis Kanavos | * without modification, are permitted provided that the following |
9 | 255f5f86 | Panagiotis Kanavos | * conditions are met: |
10 | 255f5f86 | Panagiotis Kanavos | * |
11 | 255f5f86 | Panagiotis Kanavos | * 1. Redistributions of source code must retain the above |
12 | 255f5f86 | Panagiotis Kanavos | * copyright notice, this list of conditions and the following |
13 | 255f5f86 | Panagiotis Kanavos | * disclaimer. |
14 | 255f5f86 | Panagiotis Kanavos | * |
15 | 255f5f86 | Panagiotis Kanavos | * 2. Redistributions in binary form must reproduce the above |
16 | 255f5f86 | Panagiotis Kanavos | * copyright notice, this list of conditions and the following |
17 | 255f5f86 | Panagiotis Kanavos | * disclaimer in the documentation and/or other materials |
18 | 255f5f86 | Panagiotis Kanavos | * provided with the distribution. |
19 | 255f5f86 | Panagiotis Kanavos | * |
20 | 255f5f86 | Panagiotis Kanavos | * |
21 | 255f5f86 | Panagiotis Kanavos | * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
22 | 255f5f86 | Panagiotis Kanavos | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
23 | 255f5f86 | Panagiotis Kanavos | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | 255f5f86 | Panagiotis Kanavos | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
25 | 255f5f86 | Panagiotis Kanavos | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | 255f5f86 | Panagiotis Kanavos | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 | 255f5f86 | Panagiotis Kanavos | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
28 | 255f5f86 | Panagiotis Kanavos | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
29 | 255f5f86 | Panagiotis Kanavos | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | 255f5f86 | Panagiotis Kanavos | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
31 | 255f5f86 | Panagiotis Kanavos | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | 255f5f86 | Panagiotis Kanavos | * POSSIBILITY OF SUCH DAMAGE. |
33 | 255f5f86 | Panagiotis Kanavos | * |
34 | 255f5f86 | Panagiotis Kanavos | * The views and conclusions contained in the software and |
35 | 255f5f86 | Panagiotis Kanavos | * documentation are those of the authors and should not be |
36 | 255f5f86 | Panagiotis Kanavos | * interpreted as representing official policies, either expressed |
37 | 255f5f86 | Panagiotis Kanavos | * or implied, of GRNET S.A. |
38 | 255f5f86 | Panagiotis Kanavos | * </copyright> |
39 | 255f5f86 | Panagiotis Kanavos | * ----------------------------------------------------------------------- |
40 | 255f5f86 | Panagiotis Kanavos | */ |
41 | 255f5f86 | Panagiotis Kanavos | #endregion |
42 | 255f5f86 | Panagiotis Kanavos | using System; |
43 | 9c4346c9 | Panagiotis Kanavos | using System.Collections.Generic; |
44 | 9c4346c9 | Panagiotis Kanavos | using System.ComponentModel.Composition; |
45 | 9c4346c9 | Panagiotis Kanavos | using System.Diagnostics; |
46 | bfc13ed8 | Panagiotis Kanavos | using System.Diagnostics.Contracts; |
47 | 9c4346c9 | Panagiotis Kanavos | using System.IO; |
48 | 9c4346c9 | Panagiotis Kanavos | using System.Linq; |
49 | 9c4346c9 | Panagiotis Kanavos | using System.Text; |
50 | a64c87c8 | Panagiotis Kanavos | using System.Threading.Tasks; |
51 | 9c4346c9 | Panagiotis Kanavos | using Pithos.Interfaces; |
52 | 1caef52e | Panagiotis Kanavos | using Pithos.Network; |
53 | 5120f3cb | Panagiotis Kanavos | using log4net; |
54 | 5120f3cb | Panagiotis Kanavos | using log4net.Core; |
55 | 9c4346c9 | Panagiotis Kanavos | |
56 | 9c4346c9 | Panagiotis Kanavos | namespace Pithos.Core.Agents |
57 | 9c4346c9 | Panagiotis Kanavos | { |
58 | 4ec636f6 | Panagiotis Kanavos | // [Export] |
59 | 1caef52e | Panagiotis Kanavos | public class FileAgent |
60 | 9c4346c9 | Panagiotis Kanavos | { |
61 | 4ec636f6 | Panagiotis Kanavos | Agent<WorkflowState> _agent; |
62 | 9c4346c9 | Panagiotis Kanavos | private FileSystemWatcher _watcher; |
63 | 78ebfd2d | Panagiotis Kanavos | private FileSystemWatcherAdapter _adapter; |
64 | 9c4346c9 | Panagiotis Kanavos | |
65 | 4ec636f6 | Panagiotis Kanavos | //[Import] |
66 | 9c4346c9 | Panagiotis Kanavos | public IStatusKeeper StatusKeeper { get; set; } |
67 | 4ec636f6 | Panagiotis Kanavos | //[Import] |
68 | 9c4346c9 | Panagiotis Kanavos | public IPithosWorkflow Workflow { get; set; } |
69 | 4ec636f6 | Panagiotis Kanavos | //[Import] |
70 | 9c4346c9 | Panagiotis Kanavos | public WorkflowAgent WorkflowAgent { get; set; } |
71 | 9c4346c9 | Panagiotis Kanavos | |
72 | c53aa229 | Panagiotis Kanavos | private AccountInfo AccountInfo { get; set; } |
73 | c53aa229 | Panagiotis Kanavos | |
74 | b666b39a | Panagiotis Kanavos | internal string RootPath { get; set; } |
75 | 1caef52e | Panagiotis Kanavos | |
76 | 5120f3cb | Panagiotis Kanavos | private static readonly ILog Log = LogManager.GetLogger("FileAgent"); |
77 | cfed7823 | Panagiotis Kanavos | |
78 | 4ec636f6 | Panagiotis Kanavos | public void Start(AccountInfo accountInfo,string rootPath) |
79 | 9c4346c9 | Panagiotis Kanavos | { |
80 | 4ec636f6 | Panagiotis Kanavos | if (accountInfo==null) |
81 | 4ec636f6 | Panagiotis Kanavos | throw new ArgumentNullException("accountInfo"); |
82 | 4ec636f6 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(rootPath)) |
83 | 4ec636f6 | Panagiotis Kanavos | throw new ArgumentNullException("rootPath"); |
84 | 4ec636f6 | Panagiotis Kanavos | if (!Path.IsPathRooted(rootPath)) |
85 | 4ec636f6 | Panagiotis Kanavos | throw new ArgumentException("rootPath must be an absolute path","rootPath"); |
86 | 4ec636f6 | Panagiotis Kanavos | Contract.EndContractBlock(); |
87 | 4ec636f6 | Panagiotis Kanavos | |
88 | 4ec636f6 | Panagiotis Kanavos | AccountInfo = accountInfo; |
89 | 4ec636f6 | Panagiotis Kanavos | RootPath = rootPath; |
90 | 78ebfd2d | Panagiotis Kanavos | _watcher = new FileSystemWatcher(rootPath) {IncludeSubdirectories = true}; |
91 | 78ebfd2d | Panagiotis Kanavos | _adapter = new FileSystemWatcherAdapter(_watcher); |
92 | 78ebfd2d | Panagiotis Kanavos | |
93 | 78ebfd2d | Panagiotis Kanavos | _adapter.Changed += OnFileEvent; |
94 | 78ebfd2d | Panagiotis Kanavos | _adapter.Created += OnFileEvent; |
95 | 78ebfd2d | Panagiotis Kanavos | _adapter.Deleted += OnFileEvent; |
96 | 78ebfd2d | Panagiotis Kanavos | _adapter.Renamed += OnRenameEvent; |
97 | 78ebfd2d | Panagiotis Kanavos | _adapter.Moved += OnMoveEvent; |
98 | 4ec636f6 | Panagiotis Kanavos | _watcher.EnableRaisingEvents = true; |
99 | 4ec636f6 | Panagiotis Kanavos | |
100 | 4ec636f6 | Panagiotis Kanavos | |
101 | 4ec636f6 | Panagiotis Kanavos | _agent = Agent<WorkflowState>.Start(inbox => |
102 | 4ec636f6 | Panagiotis Kanavos | { |
103 | 4ec636f6 | Panagiotis Kanavos | Action loop = null; |
104 | 4ec636f6 | Panagiotis Kanavos | loop = () => |
105 | 4ec636f6 | Panagiotis Kanavos | { |
106 | 4ec636f6 | Panagiotis Kanavos | var message = inbox.Receive(); |
107 | 139ac1e8 | Panagiotis Kanavos | var process=message.Then(Process,inbox.CancellationToken); |
108 | 4ec636f6 | Panagiotis Kanavos | inbox.LoopAsync(process,loop,ex=> |
109 | 4ec636f6 | Panagiotis Kanavos | Log.ErrorFormat("[ERROR] File Event Processing:\r{0}", ex)); |
110 | 4ec636f6 | Panagiotis Kanavos | }; |
111 | 4ec636f6 | Panagiotis Kanavos | loop(); |
112 | 4ec636f6 | Panagiotis Kanavos | }); |
113 | 9c4346c9 | Panagiotis Kanavos | } |
114 | 9c4346c9 | Panagiotis Kanavos | |
115 | 4ec636f6 | Panagiotis Kanavos | private Task<object> Process(WorkflowState state) |
116 | a64c87c8 | Panagiotis Kanavos | { |
117 | 4ec636f6 | Panagiotis Kanavos | if (state==null) |
118 | 4ec636f6 | Panagiotis Kanavos | throw new ArgumentNullException("state"); |
119 | 4ec636f6 | Panagiotis Kanavos | Contract.EndContractBlock(); |
120 | 4ec636f6 | Panagiotis Kanavos | |
121 | 4f6d51d4 | Panagiotis Kanavos | if (Ignore(state.Path)) |
122 | 4f6d51d4 | Panagiotis Kanavos | return CompletedTask<object>.Default; |
123 | 4ec636f6 | Panagiotis Kanavos | |
124 | 4ec636f6 | Panagiotis Kanavos | var networkState = NetworkGate.GetNetworkState(state.Path); |
125 | 4ec636f6 | Panagiotis Kanavos | //Skip if the file is already being downloaded or uploaded and |
126 | 4ec636f6 | Panagiotis Kanavos | //the change is create or modify |
127 | 4ec636f6 | Panagiotis Kanavos | if (networkState != NetworkOperation.None && |
128 | 4ec636f6 | Panagiotis Kanavos | ( |
129 | 4ec636f6 | Panagiotis Kanavos | state.TriggeringChange == WatcherChangeTypes.Created || |
130 | 4ec636f6 | Panagiotis Kanavos | state.TriggeringChange == WatcherChangeTypes.Changed |
131 | 4ec636f6 | Panagiotis Kanavos | )) |
132 | 4ec636f6 | Panagiotis Kanavos | return CompletedTask<object>.Default; |
133 | a64c87c8 | Panagiotis Kanavos | |
134 | a64c87c8 | Panagiotis Kanavos | try |
135 | a64c87c8 | Panagiotis Kanavos | { |
136 | 4ec636f6 | Panagiotis Kanavos | UpdateFileStatus(state); |
137 | 4ec636f6 | Panagiotis Kanavos | UpdateOverlayStatus(state); |
138 | 4ec636f6 | Panagiotis Kanavos | UpdateFileChecksum(state); |
139 | 4ec636f6 | Panagiotis Kanavos | WorkflowAgent.Post(state); |
140 | a64c87c8 | Panagiotis Kanavos | } |
141 | a64c87c8 | Panagiotis Kanavos | catch (IOException exc) |
142 | a64c87c8 | Panagiotis Kanavos | { |
143 | 4ec636f6 | Panagiotis Kanavos | if (File.Exists(state.Path)) |
144 | 0af3141d | Panagiotis Kanavos | { |
145 | 4ec636f6 | Panagiotis Kanavos | Log.WarnFormat("File access error occured, retrying {0}\n{1}", state.Path, exc); |
146 | 4ec636f6 | Panagiotis Kanavos | _agent.Post(state); |
147 | 0af3141d | Panagiotis Kanavos | } |
148 | 0af3141d | Panagiotis Kanavos | else |
149 | 0af3141d | Panagiotis Kanavos | { |
150 | 4ec636f6 | Panagiotis Kanavos | Log.WarnFormat("File {0} does not exist. Will be ignored\n{1}", state.Path, exc); |
151 | 0af3141d | Panagiotis Kanavos | } |
152 | a64c87c8 | Panagiotis Kanavos | } |
153 | a64c87c8 | Panagiotis Kanavos | catch (Exception exc) |
154 | a64c87c8 | Panagiotis Kanavos | { |
155 | 4ec636f6 | Panagiotis Kanavos | Log.WarnFormat("Error occured while indexing{0}. The file will be skipped\n{1}", |
156 | 4ec636f6 | Panagiotis Kanavos | state.Path, exc); |
157 | a64c87c8 | Panagiotis Kanavos | } |
158 | 4ec636f6 | Panagiotis Kanavos | return CompletedTask<object>.Default; |
159 | 5e31048f | Panagiotis Kanavos | } |
160 | a64c87c8 | Panagiotis Kanavos | |
161 | 9c4346c9 | Panagiotis Kanavos | public bool Pause |
162 | 9c4346c9 | Panagiotis Kanavos | { |
163 | 9c4346c9 | Panagiotis Kanavos | get { return _watcher == null || !_watcher.EnableRaisingEvents; } |
164 | 9c4346c9 | Panagiotis Kanavos | set |
165 | 9c4346c9 | Panagiotis Kanavos | { |
166 | 9c4346c9 | Panagiotis Kanavos | if (_watcher != null) |
167 | 9c4346c9 | Panagiotis Kanavos | _watcher.EnableRaisingEvents = !value; |
168 | 9c4346c9 | Panagiotis Kanavos | } |
169 | 9c4346c9 | Panagiotis Kanavos | } |
170 | 9c4346c9 | Panagiotis Kanavos | |
171 | 77e10b4f | Panagiotis Kanavos | public string CachePath { get; set; } |
172 | 1caef52e | Panagiotis Kanavos | |
173 | d3a13891 | Panagiotis Kanavos | private List<string> _selectivePaths = new List<string>(); |
174 | d3a13891 | Panagiotis Kanavos | public List<string> SelectivePaths |
175 | d3a13891 | Panagiotis Kanavos | { |
176 | d3a13891 | Panagiotis Kanavos | get { return _selectivePaths; } |
177 | d3a13891 | Panagiotis Kanavos | set { _selectivePaths = value; } |
178 | d3a13891 | Panagiotis Kanavos | } |
179 | d3a13891 | Panagiotis Kanavos | |
180 | d3a13891 | Panagiotis Kanavos | |
181 | 9c4346c9 | Panagiotis Kanavos | public void Post(WorkflowState workflowState) |
182 | 9c4346c9 | Panagiotis Kanavos | { |
183 | cfed7823 | Panagiotis Kanavos | if (workflowState == null) |
184 | cfed7823 | Panagiotis Kanavos | throw new ArgumentNullException("workflowState"); |
185 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
186 | cfed7823 | Panagiotis Kanavos | |
187 | 9c4346c9 | Panagiotis Kanavos | _agent.Post(workflowState); |
188 | 9c4346c9 | Panagiotis Kanavos | } |
189 | 9c4346c9 | Panagiotis Kanavos | |
190 | 9c4346c9 | Panagiotis Kanavos | public void Stop() |
191 | 9c4346c9 | Panagiotis Kanavos | { |
192 | 9c4346c9 | Panagiotis Kanavos | if (_watcher != null) |
193 | 9c4346c9 | Panagiotis Kanavos | { |
194 | 9c4346c9 | Panagiotis Kanavos | _watcher.Changed -= OnFileEvent; |
195 | 9c4346c9 | Panagiotis Kanavos | _watcher.Created -= OnFileEvent; |
196 | 9c4346c9 | Panagiotis Kanavos | _watcher.Deleted -= OnFileEvent; |
197 | 9c4346c9 | Panagiotis Kanavos | _watcher.Renamed -= OnRenameEvent; |
198 | 9c4346c9 | Panagiotis Kanavos | _watcher.Dispose(); |
199 | 9c4346c9 | Panagiotis Kanavos | } |
200 | 9c4346c9 | Panagiotis Kanavos | _watcher = null; |
201 | 9c4346c9 | Panagiotis Kanavos | |
202 | cfed7823 | Panagiotis Kanavos | if (_agent!=null) |
203 | 4ec636f6 | Panagiotis Kanavos | _agent.Stop(); |
204 | 9c4346c9 | Panagiotis Kanavos | } |
205 | 9c4346c9 | Panagiotis Kanavos | |
206 | 1caef52e | Panagiotis Kanavos | // Enumerate all files in the Pithos directory except those in the Fragment folder |
207 | 1caef52e | Panagiotis Kanavos | // and files with a .ignore extension |
208 | 1caef52e | Panagiotis Kanavos | public IEnumerable<string> EnumerateFiles(string searchPattern="*") |
209 | 1caef52e | Panagiotis Kanavos | { |
210 | 1caef52e | Panagiotis Kanavos | var monitoredFiles = from filePath in Directory.EnumerateFileSystemEntries(RootPath, searchPattern, SearchOption.AllDirectories) |
211 | 1caef52e | Panagiotis Kanavos | where !Ignore(filePath) |
212 | 1caef52e | Panagiotis Kanavos | select filePath; |
213 | 1caef52e | Panagiotis Kanavos | return monitoredFiles; |
214 | 1caef52e | Panagiotis Kanavos | } |
215 | 1caef52e | Panagiotis Kanavos | |
216 | 1caef52e | Panagiotis Kanavos | public IEnumerable<FileInfo> EnumerateFileInfos(string searchPattern="*") |
217 | 1caef52e | Panagiotis Kanavos | { |
218 | 1caef52e | Panagiotis Kanavos | var rootDir = new DirectoryInfo(RootPath); |
219 | 1caef52e | Panagiotis Kanavos | var monitoredFiles = from file in rootDir.EnumerateFiles(searchPattern, SearchOption.AllDirectories) |
220 | 1caef52e | Panagiotis Kanavos | where !Ignore(file.FullName) |
221 | 1caef52e | Panagiotis Kanavos | select file; |
222 | 1caef52e | Panagiotis Kanavos | return monitoredFiles; |
223 | 1caef52e | Panagiotis Kanavos | } |
224 | 1caef52e | Panagiotis Kanavos | |
225 | 1caef52e | Panagiotis Kanavos | public IEnumerable<string> EnumerateFilesAsRelativeUrls(string searchPattern="*") |
226 | 1caef52e | Panagiotis Kanavos | { |
227 | 1caef52e | Panagiotis Kanavos | var rootDir = new DirectoryInfo(RootPath); |
228 | 1caef52e | Panagiotis Kanavos | var monitoredFiles = from file in rootDir.EnumerateFiles(searchPattern, SearchOption.AllDirectories) |
229 | 1caef52e | Panagiotis Kanavos | where !Ignore(file.FullName) |
230 | 1caef52e | Panagiotis Kanavos | select file.AsRelativeUrlTo(RootPath); |
231 | 1caef52e | Panagiotis Kanavos | return monitoredFiles; |
232 | 1caef52e | Panagiotis Kanavos | } |
233 | 1caef52e | Panagiotis Kanavos | |
234 | 540b8cf8 | Panagiotis Kanavos | public IEnumerable<string> EnumerateFilesSystemInfosAsRelativeUrls(string searchPattern="*") |
235 | 540b8cf8 | Panagiotis Kanavos | { |
236 | 540b8cf8 | Panagiotis Kanavos | var rootDir = new DirectoryInfo(RootPath); |
237 | 540b8cf8 | Panagiotis Kanavos | var monitoredFiles = from file in rootDir.EnumerateFileSystemInfos(searchPattern, SearchOption.AllDirectories) |
238 | 540b8cf8 | Panagiotis Kanavos | where !Ignore(file.FullName) |
239 | 540b8cf8 | Panagiotis Kanavos | select file.AsRelativeUrlTo(RootPath); |
240 | 540b8cf8 | Panagiotis Kanavos | return monitoredFiles; |
241 | 540b8cf8 | Panagiotis Kanavos | } |
242 | 540b8cf8 | Panagiotis Kanavos | |
243 | 1caef52e | Panagiotis Kanavos | |
244 | 1caef52e | Panagiotis Kanavos | |
245 | 1caef52e | Panagiotis Kanavos | |
246 | 1caef52e | Panagiotis Kanavos | private bool Ignore(string filePath) |
247 | 1caef52e | Panagiotis Kanavos | { |
248 | 139ac1e8 | Panagiotis Kanavos | //Ignore all first-level directories and files (ie at the container folders level) |
249 | d9b1cbeb | Panagiotis Kanavos | if (FoundBelowRoot(filePath, RootPath,1)) |
250 | 139ac1e8 | Panagiotis Kanavos | return true; |
251 | d9b1cbeb | Panagiotis Kanavos | |
252 | 139ac1e8 | Panagiotis Kanavos | //Ignore first-level items under the "others" folder (ie at the accounts folders level). |
253 | d9b1cbeb | Panagiotis Kanavos | var othersPath = Path.Combine(RootPath, FolderConstants.OthersFolder); |
254 | d9b1cbeb | Panagiotis Kanavos | if (FoundBelowRoot(filePath, othersPath,1)) |
255 | 139ac1e8 | Panagiotis Kanavos | return true; |
256 | d9b1cbeb | Panagiotis Kanavos | |
257 | 139ac1e8 | Panagiotis Kanavos | //Ignore second-level (container) folders under the "others" folder (ie at the container folders level). |
258 | d9b1cbeb | Panagiotis Kanavos | if (FoundBelowRoot(filePath, othersPath,2)) |
259 | d9b1cbeb | Panagiotis Kanavos | return true; |
260 | d9b1cbeb | Panagiotis Kanavos | |
261 | d9b1cbeb | Panagiotis Kanavos | |
262 | d9b1cbeb | Panagiotis Kanavos | //Ignore anything happening in the cache path |
263 | 77e10b4f | Panagiotis Kanavos | if (filePath.StartsWith(CachePath)) |
264 | 1caef52e | Panagiotis Kanavos | return true; |
265 | 0af3141d | Panagiotis Kanavos | if (_ignoreFiles.ContainsKey(filePath.ToLower())) |
266 | 0af3141d | Panagiotis Kanavos | return true; |
267 | 139ac1e8 | Panagiotis Kanavos | |
268 | fec5da06 | Panagiotis Kanavos | //Ignore if selective synchronization is defined, |
269 | fec5da06 | Panagiotis Kanavos | return SelectivePaths.Count > 0 |
270 | fec5da06 | Panagiotis Kanavos | //And the target file is not below any of the selective paths |
271 | fec5da06 | Panagiotis Kanavos | && !SelectivePaths.Any(filePath.IsAtOrDirectlyBelow); |
272 | 1caef52e | Panagiotis Kanavos | } |
273 | 1caef52e | Panagiotis Kanavos | |
274 | d9b1cbeb | Panagiotis Kanavos | /* private static bool FoundInRoot(string filePath, string rootPath) |
275 | d9b1cbeb | Panagiotis Kanavos | { |
276 | d9b1cbeb | Panagiotis Kanavos | //var rootDirectory = new DirectoryInfo(rootPath); |
277 | d9b1cbeb | Panagiotis Kanavos | |
278 | d9b1cbeb | Panagiotis Kanavos | //If the paths are equal, return true |
279 | d9b1cbeb | Panagiotis Kanavos | if (filePath.Equals(rootPath, StringComparison.InvariantCultureIgnoreCase)) |
280 | d9b1cbeb | Panagiotis Kanavos | return true; |
281 | d9b1cbeb | Panagiotis Kanavos | |
282 | d9b1cbeb | Panagiotis Kanavos | //If the filepath is below the root path |
283 | d9b1cbeb | Panagiotis Kanavos | if (filePath.StartsWith(rootPath,StringComparison.InvariantCulture)) |
284 | d9b1cbeb | Panagiotis Kanavos | { |
285 | d9b1cbeb | Panagiotis Kanavos | //Get the relative path |
286 | d9b1cbeb | Panagiotis Kanavos | var relativePath = filePath.Substring(rootPath.Length + 1); |
287 | d9b1cbeb | Panagiotis Kanavos | //If the relativePath does NOT contains a path separator, we found a match |
288 | d9b1cbeb | Panagiotis Kanavos | return (!relativePath.Contains(@"\")); |
289 | d9b1cbeb | Panagiotis Kanavos | } |
290 | d9b1cbeb | Panagiotis Kanavos | |
291 | d9b1cbeb | Panagiotis Kanavos | //If the filepath is not under the root path, return false |
292 | d9b1cbeb | Panagiotis Kanavos | return false; |
293 | d9b1cbeb | Panagiotis Kanavos | }*/ |
294 | d9b1cbeb | Panagiotis Kanavos | |
295 | d9b1cbeb | Panagiotis Kanavos | |
296 | d9b1cbeb | Panagiotis Kanavos | private static bool FoundBelowRoot(string filePath, string rootPath,int level) |
297 | d9b1cbeb | Panagiotis Kanavos | { |
298 | d9b1cbeb | Panagiotis Kanavos | //var rootDirectory = new DirectoryInfo(rootPath); |
299 | d9b1cbeb | Panagiotis Kanavos | |
300 | d9b1cbeb | Panagiotis Kanavos | //If the paths are equal, return true |
301 | d9b1cbeb | Panagiotis Kanavos | if (filePath.Equals(rootPath, StringComparison.InvariantCultureIgnoreCase)) |
302 | d9b1cbeb | Panagiotis Kanavos | return true; |
303 | d9b1cbeb | Panagiotis Kanavos | |
304 | d9b1cbeb | Panagiotis Kanavos | //If the filepath is below the root path |
305 | d9b1cbeb | Panagiotis Kanavos | if (filePath.StartsWith(rootPath,StringComparison.InvariantCulture)) |
306 | d9b1cbeb | Panagiotis Kanavos | { |
307 | d9b1cbeb | Panagiotis Kanavos | //Get the relative path |
308 | d9b1cbeb | Panagiotis Kanavos | var relativePath = filePath.Substring(rootPath.Length + 1); |
309 | d9b1cbeb | Panagiotis Kanavos | //If the relativePath does NOT contains a path separator, we found a match |
310 | d9b1cbeb | Panagiotis Kanavos | var levels=relativePath.ToCharArray().Count(c=>c=='\\')+1; |
311 | d9b1cbeb | Panagiotis Kanavos | return levels==level; |
312 | d9b1cbeb | Panagiotis Kanavos | } |
313 | d9b1cbeb | Panagiotis Kanavos | |
314 | d9b1cbeb | Panagiotis Kanavos | //If the filepath is not under the root path, return false |
315 | d9b1cbeb | Panagiotis Kanavos | return false; |
316 | d9b1cbeb | Panagiotis Kanavos | } |
317 | d9b1cbeb | Panagiotis Kanavos | |
318 | 1caef52e | Panagiotis Kanavos | //Post a Change message for all events except rename |
319 | 9c4346c9 | Panagiotis Kanavos | void OnFileEvent(object sender, FileSystemEventArgs e) |
320 | 9c4346c9 | Panagiotis Kanavos | { |
321 | 77e10b4f | Panagiotis Kanavos | //Ignore events that affect the cache folder |
322 | 1caef52e | Panagiotis Kanavos | var filePath = e.FullPath; |
323 | 1caef52e | Panagiotis Kanavos | if (Ignore(filePath)) |
324 | a0dcfcc9 | Panagiotis Kanavos | return; |
325 | 3c76f045 | Panagiotis Kanavos | |
326 | 1bfc38f1 | Panagiotis Kanavos | _agent.Post(new WorkflowState{AccountInfo=AccountInfo, Path = filePath, FileName = e.Name, TriggeringChange = e.ChangeType }); |
327 | 9c4346c9 | Panagiotis Kanavos | } |
328 | 9c4346c9 | Panagiotis Kanavos | |
329 | 1caef52e | Panagiotis Kanavos | |
330 | 1caef52e | Panagiotis Kanavos | //Post a Change message for renames containing the old and new names |
331 | 9c4346c9 | Panagiotis Kanavos | void OnRenameEvent(object sender, RenamedEventArgs e) |
332 | 9c4346c9 | Panagiotis Kanavos | { |
333 | 1caef52e | Panagiotis Kanavos | var oldFullPath = e.OldFullPath; |
334 | 1caef52e | Panagiotis Kanavos | var fullPath = e.FullPath; |
335 | 1caef52e | Panagiotis Kanavos | if (Ignore(oldFullPath) || Ignore(fullPath)) |
336 | 1caef52e | Panagiotis Kanavos | return; |
337 | 1caef52e | Panagiotis Kanavos | |
338 | 1bfc38f1 | Panagiotis Kanavos | _agent.Post(new WorkflowState |
339 | 9c4346c9 | Panagiotis Kanavos | { |
340 | 1bfc38f1 | Panagiotis Kanavos | AccountInfo=AccountInfo, |
341 | 1caef52e | Panagiotis Kanavos | OldPath = oldFullPath, |
342 | 9c4346c9 | Panagiotis Kanavos | OldFileName = e.OldName, |
343 | 1caef52e | Panagiotis Kanavos | Path = fullPath, |
344 | 9c4346c9 | Panagiotis Kanavos | FileName = e.Name, |
345 | 78ebfd2d | Panagiotis Kanavos | TriggeringChange = e.ChangeType |
346 | 78ebfd2d | Panagiotis Kanavos | }); |
347 | 78ebfd2d | Panagiotis Kanavos | } |
348 | 78ebfd2d | Panagiotis Kanavos | |
349 | 78ebfd2d | Panagiotis Kanavos | //Post a Change message for renames containing the old and new names |
350 | 78ebfd2d | Panagiotis Kanavos | void OnMoveEvent(object sender, MovedEventArgs e) |
351 | 78ebfd2d | Panagiotis Kanavos | { |
352 | 78ebfd2d | Panagiotis Kanavos | var oldFullPath = e.OldFullPath; |
353 | 78ebfd2d | Panagiotis Kanavos | var fullPath = e.FullPath; |
354 | 78ebfd2d | Panagiotis Kanavos | if (Ignore(oldFullPath) || Ignore(fullPath)) |
355 | 78ebfd2d | Panagiotis Kanavos | return; |
356 | 78ebfd2d | Panagiotis Kanavos | |
357 | 78ebfd2d | Panagiotis Kanavos | _agent.Post(new WorkflowState |
358 | 78ebfd2d | Panagiotis Kanavos | { |
359 | 78ebfd2d | Panagiotis Kanavos | AccountInfo=AccountInfo, |
360 | 78ebfd2d | Panagiotis Kanavos | OldPath = oldFullPath, |
361 | 78ebfd2d | Panagiotis Kanavos | OldFileName = e.OldName, |
362 | 78ebfd2d | Panagiotis Kanavos | Path = fullPath, |
363 | 78ebfd2d | Panagiotis Kanavos | FileName = e.Name, |
364 | 9c4346c9 | Panagiotis Kanavos | TriggeringChange = e.ChangeType |
365 | 9c4346c9 | Panagiotis Kanavos | }); |
366 | 9c4346c9 | Panagiotis Kanavos | } |
367 | 9c4346c9 | Panagiotis Kanavos | |
368 | 9c4346c9 | Panagiotis Kanavos | |
369 | 9c4346c9 | Panagiotis Kanavos | |
370 | 9c4346c9 | Panagiotis Kanavos | private Dictionary<WatcherChangeTypes, FileStatus> _statusDict = new Dictionary<WatcherChangeTypes, FileStatus> |
371 | fbbbe99b | Panagiotis Kanavos | { |
372 | 9c4346c9 | Panagiotis Kanavos | {WatcherChangeTypes.Created,FileStatus.Created}, |
373 | 9c4346c9 | Panagiotis Kanavos | {WatcherChangeTypes.Changed,FileStatus.Modified}, |
374 | 9c4346c9 | Panagiotis Kanavos | {WatcherChangeTypes.Deleted,FileStatus.Deleted}, |
375 | 9c4346c9 | Panagiotis Kanavos | {WatcherChangeTypes.Renamed,FileStatus.Renamed} |
376 | 9c4346c9 | Panagiotis Kanavos | }; |
377 | 9c4346c9 | Panagiotis Kanavos | |
378 | fbbbe99b | Panagiotis Kanavos | private Dictionary<string, string> _ignoreFiles=new Dictionary<string, string>(); |
379 | 0af3141d | Panagiotis Kanavos | |
380 | 9c4346c9 | Panagiotis Kanavos | private WorkflowState UpdateFileStatus(WorkflowState state) |
381 | 9c4346c9 | Panagiotis Kanavos | { |
382 | cfed7823 | Panagiotis Kanavos | if (state==null) |
383 | cfed7823 | Panagiotis Kanavos | throw new ArgumentNullException("state"); |
384 | cfed7823 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(state.Path)) |
385 | cfed7823 | Panagiotis Kanavos | throw new ArgumentException("The state's Path can't be empty","state"); |
386 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
387 | 1caef52e | Panagiotis Kanavos | |
388 | cfed7823 | Panagiotis Kanavos | var path = state.Path; |
389 | cfed7823 | Panagiotis Kanavos | var status = _statusDict[state.TriggeringChange]; |
390 | 9c4346c9 | Panagiotis Kanavos | var oldStatus = Workflow.StatusKeeper.GetFileStatus(path); |
391 | 9c4346c9 | Panagiotis Kanavos | if (status == oldStatus) |
392 | 9c4346c9 | Panagiotis Kanavos | { |
393 | 9c4346c9 | Panagiotis Kanavos | state.Status = status; |
394 | 9c4346c9 | Panagiotis Kanavos | state.Skip = true; |
395 | 9c4346c9 | Panagiotis Kanavos | return state; |
396 | 9c4346c9 | Panagiotis Kanavos | } |
397 | 9c4346c9 | Panagiotis Kanavos | if (state.Status == FileStatus.Renamed) |
398 | 9c4346c9 | Panagiotis Kanavos | Workflow.ClearFileStatus(path); |
399 | 9c4346c9 | Panagiotis Kanavos | |
400 | 9c4346c9 | Panagiotis Kanavos | state.Status = Workflow.SetFileStatus(path, status); |
401 | 9c4346c9 | Panagiotis Kanavos | return state; |
402 | 9c4346c9 | Panagiotis Kanavos | } |
403 | 9c4346c9 | Panagiotis Kanavos | |
404 | 9c4346c9 | Panagiotis Kanavos | private WorkflowState UpdateOverlayStatus(WorkflowState state) |
405 | 9c4346c9 | Panagiotis Kanavos | { |
406 | cfed7823 | Panagiotis Kanavos | if (state==null) |
407 | cfed7823 | Panagiotis Kanavos | throw new ArgumentNullException("state"); |
408 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
409 | cfed7823 | Panagiotis Kanavos | |
410 | 9c4346c9 | Panagiotis Kanavos | if (state.Skip) |
411 | 9c4346c9 | Panagiotis Kanavos | return state; |
412 | 9c4346c9 | Panagiotis Kanavos | |
413 | 9c4346c9 | Panagiotis Kanavos | switch (state.Status) |
414 | 9c4346c9 | Panagiotis Kanavos | { |
415 | 9c4346c9 | Panagiotis Kanavos | case FileStatus.Created: |
416 | 9c4346c9 | Panagiotis Kanavos | case FileStatus.Modified: |
417 | 9c4346c9 | Panagiotis Kanavos | this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified); |
418 | 9c4346c9 | Panagiotis Kanavos | break; |
419 | 9c4346c9 | Panagiotis Kanavos | case FileStatus.Deleted: |
420 | cfed7823 | Panagiotis Kanavos | //this.StatusAgent.RemoveFileOverlayStatus(state.Path); |
421 | 9c4346c9 | Panagiotis Kanavos | break; |
422 | 9c4346c9 | Panagiotis Kanavos | case FileStatus.Renamed: |
423 | cfed7823 | Panagiotis Kanavos | this.StatusKeeper.ClearFileStatus(state.OldPath); |
424 | 9c4346c9 | Panagiotis Kanavos | this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified); |
425 | 9c4346c9 | Panagiotis Kanavos | break; |
426 | 9c4346c9 | Panagiotis Kanavos | case FileStatus.Unchanged: |
427 | 9c4346c9 | Panagiotis Kanavos | this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Normal); |
428 | 9c4346c9 | Panagiotis Kanavos | break; |
429 | 9c4346c9 | Panagiotis Kanavos | } |
430 | 9c4346c9 | Panagiotis Kanavos | |
431 | 9c4346c9 | Panagiotis Kanavos | if (state.Status == FileStatus.Deleted) |
432 | 1caef52e | Panagiotis Kanavos | NativeMethods.RaiseChangeNotification(Path.GetDirectoryName(state.Path)); |
433 | 9c4346c9 | Panagiotis Kanavos | else |
434 | 1caef52e | Panagiotis Kanavos | NativeMethods.RaiseChangeNotification(state.Path); |
435 | 9c4346c9 | Panagiotis Kanavos | return state; |
436 | 9c4346c9 | Panagiotis Kanavos | } |
437 | 9c4346c9 | Panagiotis Kanavos | |
438 | 9c4346c9 | Panagiotis Kanavos | |
439 | 9c4346c9 | Panagiotis Kanavos | private WorkflowState UpdateFileChecksum(WorkflowState state) |
440 | 9c4346c9 | Panagiotis Kanavos | { |
441 | 9c4346c9 | Panagiotis Kanavos | if (state.Skip) |
442 | 9c4346c9 | Panagiotis Kanavos | return state; |
443 | 9c4346c9 | Panagiotis Kanavos | |
444 | 9c4346c9 | Panagiotis Kanavos | if (state.Status == FileStatus.Deleted) |
445 | 9c4346c9 | Panagiotis Kanavos | return state; |
446 | 9c4346c9 | Panagiotis Kanavos | |
447 | 1caef52e | Panagiotis Kanavos | var path = state.Path; |
448 | 1caef52e | Panagiotis Kanavos | //Skip calculation for folders |
449 | 1caef52e | Panagiotis Kanavos | if (Directory.Exists(path)) |
450 | 1caef52e | Panagiotis Kanavos | return state; |
451 | 1caef52e | Panagiotis Kanavos | |
452 | 0af3141d | Panagiotis Kanavos | var info = new FileInfo(path); |
453 | 0af3141d | Panagiotis Kanavos | string hash = info.CalculateHash(StatusKeeper.BlockSize,StatusKeeper.BlockHash); |
454 | 9c4346c9 | Panagiotis Kanavos | StatusKeeper.UpdateFileChecksum(path, hash); |
455 | 9c4346c9 | Panagiotis Kanavos | |
456 | 9c4346c9 | Panagiotis Kanavos | state.Hash = hash; |
457 | 9c4346c9 | Panagiotis Kanavos | return state; |
458 | 9c4346c9 | Panagiotis Kanavos | } |
459 | 9c4346c9 | Panagiotis Kanavos | |
460 | bfc13ed8 | Panagiotis Kanavos | //Does the file exist in the container's local folder? |
461 | bfc13ed8 | Panagiotis Kanavos | public bool Exists(string relativePath) |
462 | bfc13ed8 | Panagiotis Kanavos | { |
463 | bfc13ed8 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(relativePath)) |
464 | bfc13ed8 | Panagiotis Kanavos | throw new ArgumentNullException("relativePath"); |
465 | bfc13ed8 | Panagiotis Kanavos | //A RootPath must be set before calling this method |
466 | bfc13ed8 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(RootPath)) |
467 | bfc13ed8 | Panagiotis Kanavos | throw new InvalidOperationException("RootPath was not set"); |
468 | bfc13ed8 | Panagiotis Kanavos | Contract.EndContractBlock(); |
469 | bfc13ed8 | Panagiotis Kanavos | //Create the absolute path by combining the RootPath with the relativePath |
470 | bfc13ed8 | Panagiotis Kanavos | var absolutePath=Path.Combine(RootPath, relativePath); |
471 | bfc13ed8 | Panagiotis Kanavos | //Is this a valid file? |
472 | bfc13ed8 | Panagiotis Kanavos | if (File.Exists(absolutePath)) |
473 | bfc13ed8 | Panagiotis Kanavos | return true; |
474 | bfc13ed8 | Panagiotis Kanavos | //Or a directory? |
475 | a64c87c8 | Panagiotis Kanavos | if (Directory.Exists(absolutePath)) |
476 | bfc13ed8 | Panagiotis Kanavos | return true; |
477 | bfc13ed8 | Panagiotis Kanavos | //Fail if it is neither |
478 | bfc13ed8 | Panagiotis Kanavos | return false; |
479 | bfc13ed8 | Panagiotis Kanavos | } |
480 | 9c4346c9 | Panagiotis Kanavos | |
481 | fbbbe99b | Panagiotis Kanavos | public static FileAgent GetFileAgent(AccountInfo accountInfo) |
482 | fbbbe99b | Panagiotis Kanavos | { |
483 | fbbbe99b | Panagiotis Kanavos | return GetFileAgent(accountInfo.AccountPath); |
484 | fbbbe99b | Panagiotis Kanavos | } |
485 | fbbbe99b | Panagiotis Kanavos | |
486 | fbbbe99b | Panagiotis Kanavos | public static FileAgent GetFileAgent(string rootPath) |
487 | fbbbe99b | Panagiotis Kanavos | { |
488 | fbbbe99b | Panagiotis Kanavos | return AgentLocator<FileAgent>.Get(rootPath.ToLower()); |
489 | fbbbe99b | Panagiotis Kanavos | } |
490 | fbbbe99b | Panagiotis Kanavos | |
491 | fbbbe99b | Panagiotis Kanavos | |
492 | f3d080df | Panagiotis Kanavos | public FileSystemInfo GetFileSystemInfo(string relativePath) |
493 | bfc13ed8 | Panagiotis Kanavos | { |
494 | bfc13ed8 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(relativePath)) |
495 | bfc13ed8 | Panagiotis Kanavos | throw new ArgumentNullException("relativePath"); |
496 | bfc13ed8 | Panagiotis Kanavos | //A RootPath must be set before calling this method |
497 | bfc13ed8 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(RootPath)) |
498 | bfc13ed8 | Panagiotis Kanavos | throw new InvalidOperationException("RootPath was not set"); |
499 | bfc13ed8 | Panagiotis Kanavos | Contract.EndContractBlock(); |
500 | bfc13ed8 | Panagiotis Kanavos | |
501 | bfc13ed8 | Panagiotis Kanavos | var absolutePath = Path.Combine(RootPath, relativePath); |
502 | bfc13ed8 | Panagiotis Kanavos | |
503 | 4f6d51d4 | Panagiotis Kanavos | if (Directory.Exists(absolutePath)) |
504 | f3d080df | Panagiotis Kanavos | return new DirectoryInfo(absolutePath).WithProperCapitalization(); |
505 | 4f6d51d4 | Panagiotis Kanavos | else |
506 | f3d080df | Panagiotis Kanavos | return new FileInfo(absolutePath).WithProperCapitalization(); |
507 | bfc13ed8 | Panagiotis Kanavos | |
508 | bfc13ed8 | Panagiotis Kanavos | } |
509 | a27aa447 | Panagiotis Kanavos | |
510 | 0af3141d | Panagiotis Kanavos | public void Delete(string relativePath) |
511 | 0af3141d | Panagiotis Kanavos | { |
512 | 4f6d51d4 | Panagiotis Kanavos | var absolutePath = Path.Combine(RootPath, relativePath).ToLower(); |
513 | 0af3141d | Panagiotis Kanavos | if (File.Exists(absolutePath)) |
514 | 4f6d51d4 | Panagiotis Kanavos | { |
515 | 4f6d51d4 | Panagiotis Kanavos | try |
516 | 4f6d51d4 | Panagiotis Kanavos | { |
517 | 4f6d51d4 | Panagiotis Kanavos | File.Delete(absolutePath); |
518 | 4f6d51d4 | Panagiotis Kanavos | } |
519 | 4f6d51d4 | Panagiotis Kanavos | //The file may have been deleted by another thread. Just ignore the relevant exception |
520 | 4f6d51d4 | Panagiotis Kanavos | catch (FileNotFoundException) { } |
521 | 4f6d51d4 | Panagiotis Kanavos | } |
522 | 4f6d51d4 | Panagiotis Kanavos | else if (Directory.Exists(absolutePath)) |
523 | 4f6d51d4 | Panagiotis Kanavos | { |
524 | 4f6d51d4 | Panagiotis Kanavos | try |
525 | 4f6d51d4 | Panagiotis Kanavos | { |
526 | 4f6d51d4 | Panagiotis Kanavos | Directory.Delete(absolutePath, true); |
527 | 4f6d51d4 | Panagiotis Kanavos | } |
528 | 4f6d51d4 | Panagiotis Kanavos | //The directory may have been deleted by another thread. Just ignore the relevant exception |
529 | 4f6d51d4 | Panagiotis Kanavos | catch (DirectoryNotFoundException){} |
530 | 0af3141d | Panagiotis Kanavos | } |
531 | 4f6d51d4 | Panagiotis Kanavos | |
532 | 4f6d51d4 | Panagiotis Kanavos | //_ignoreFiles[absolutePath] = absolutePath; |
533 | 0af3141d | Panagiotis Kanavos | StatusKeeper.ClearFileStatus(absolutePath); |
534 | 0af3141d | Panagiotis Kanavos | } |
535 | 9c4346c9 | Panagiotis Kanavos | } |
536 | 9c4346c9 | Panagiotis Kanavos | } |