Statistics
| Branch: | Revision:

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
}