Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / Agents / FileAgent.cs @ d21f3c77

History | View | Annotate | Download (22.1 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 bfc13ed8 Panagiotis Kanavos
using System.Diagnostics.Contracts;
45 9c4346c9 Panagiotis Kanavos
using System.IO;
46 9c4346c9 Panagiotis Kanavos
using System.Linq;
47 db8a9589 Panagiotis Kanavos
using System.Reflection;
48 a64c87c8 Panagiotis Kanavos
using System.Threading.Tasks;
49 9c4346c9 Panagiotis Kanavos
using Pithos.Interfaces;
50 1caef52e Panagiotis Kanavos
using Pithos.Network;
51 5120f3cb Panagiotis Kanavos
using log4net;
52 9c4346c9 Panagiotis Kanavos
53 9c4346c9 Panagiotis Kanavos
namespace Pithos.Core.Agents
54 9c4346c9 Panagiotis Kanavos
{
55 4ec636f6 Panagiotis Kanavos
//    [Export]
56 1caef52e Panagiotis Kanavos
    public class FileAgent
57 9c4346c9 Panagiotis Kanavos
    {
58 db8a9589 Panagiotis Kanavos
        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 db8a9589 Panagiotis Kanavos
60 4ec636f6 Panagiotis Kanavos
        Agent<WorkflowState> _agent;
61 9c4346c9 Panagiotis Kanavos
        private FileSystemWatcher _watcher;
62 78ebfd2d Panagiotis Kanavos
        private FileSystemWatcherAdapter _adapter;
63 9c4346c9 Panagiotis Kanavos
64 4ec636f6 Panagiotis Kanavos
        //[Import]
65 9c4346c9 Panagiotis Kanavos
        public IStatusKeeper StatusKeeper { get; set; }
66 174bbb6e Panagiotis Kanavos
67 174bbb6e Panagiotis Kanavos
        public IStatusNotification StatusNotification { get; set; }
68 4ec636f6 Panagiotis Kanavos
        //[Import]
69 9c4346c9 Panagiotis Kanavos
        public IPithosWorkflow Workflow { get; set; }
70 4ec636f6 Panagiotis Kanavos
        //[Import]
71 9c4346c9 Panagiotis Kanavos
        public WorkflowAgent WorkflowAgent { get; set; }
72 9c4346c9 Panagiotis Kanavos
73 c53aa229 Panagiotis Kanavos
        private AccountInfo AccountInfo { get; set; }
74 c53aa229 Panagiotis Kanavos
75 b666b39a Panagiotis Kanavos
        internal string RootPath { get;  set; }
76 79f92570 Panagiotis Kanavos
        
77 79f92570 Panagiotis Kanavos
        private FileEventIdleBatch _eventIdleBatch;
78 79f92570 Panagiotis Kanavos
79 5d7b20e8 Panagiotis Kanavos
        public TimeSpan IdleTimeout { get; set; }
80 5d7b20e8 Panagiotis Kanavos
81 1caef52e Panagiotis Kanavos
82 79f92570 Panagiotis Kanavos
        private void ProcessBatchedEvents(Dictionary<string, FileSystemEventArgs[]> fileEvents)
83 79f92570 Panagiotis Kanavos
        {
84 79f92570 Panagiotis Kanavos
            StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,String.Format("Uploading {0} files",fileEvents.Count));
85 79f92570 Panagiotis Kanavos
            foreach (var fileEvent in fileEvents)
86 79f92570 Panagiotis Kanavos
            {
87 79f92570 Panagiotis Kanavos
                var filePath = fileEvent.Key;
88 79f92570 Panagiotis Kanavos
                var changes = fileEvent.Value;
89 79f92570 Panagiotis Kanavos
                
90 79f92570 Panagiotis Kanavos
                if (Ignore(filePath)) continue;
91 79f92570 Panagiotis Kanavos
                                
92 79f92570 Panagiotis Kanavos
                foreach (var change in changes)
93 79f92570 Panagiotis Kanavos
                {
94 79f92570 Panagiotis Kanavos
                    if (change.ChangeType == WatcherChangeTypes.Renamed)
95 79f92570 Panagiotis Kanavos
                    {
96 6b0de454 Panagiotis Kanavos
                        var rename = (MovedEventArgs) change;
97 79f92570 Panagiotis Kanavos
                        _agent.Post(new WorkflowState
98 79f92570 Panagiotis Kanavos
                                        {
99 79f92570 Panagiotis Kanavos
                                            AccountInfo = AccountInfo,
100 79f92570 Panagiotis Kanavos
                                            OldPath = rename.OldFullPath,
101 6b0de454 Panagiotis Kanavos
                                            OldFileName = Path.GetFileName(rename.OldName),
102 79f92570 Panagiotis Kanavos
                                            Path = rename.FullPath,
103 6b0de454 Panagiotis Kanavos
                                            FileName = Path.GetFileName(rename.Name),
104 79f92570 Panagiotis Kanavos
                                            TriggeringChange = rename.ChangeType
105 79f92570 Panagiotis Kanavos
                                        });
106 79f92570 Panagiotis Kanavos
                    }
107 79f92570 Panagiotis Kanavos
                    else
108 79f92570 Panagiotis Kanavos
                        _agent.Post(new WorkflowState
109 79f92570 Panagiotis Kanavos
                        {
110 79f92570 Panagiotis Kanavos
                            AccountInfo = AccountInfo,
111 79f92570 Panagiotis Kanavos
                            Path = change.FullPath,
112 6b0de454 Panagiotis Kanavos
                            FileName = Path.GetFileName(change.Name),
113 79f92570 Panagiotis Kanavos
                            TriggeringChange = change.ChangeType
114 79f92570 Panagiotis Kanavos
                        });                        
115 79f92570 Panagiotis Kanavos
                }
116 79f92570 Panagiotis Kanavos
            }
117 79f92570 Panagiotis Kanavos
            StatusNotification.SetPithosStatus(PithosStatus.LocalComplete);
118 79f92570 Panagiotis Kanavos
        }
119 cfed7823 Panagiotis Kanavos
120 4ec636f6 Panagiotis Kanavos
        public void Start(AccountInfo accountInfo,string rootPath)
121 9c4346c9 Panagiotis Kanavos
        {
122 4ec636f6 Panagiotis Kanavos
            if (accountInfo==null)
123 4ec636f6 Panagiotis Kanavos
                throw new ArgumentNullException("accountInfo");
124 4ec636f6 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(rootPath))
125 4ec636f6 Panagiotis Kanavos
                throw new ArgumentNullException("rootPath");
126 4ec636f6 Panagiotis Kanavos
            if (!Path.IsPathRooted(rootPath))
127 4ec636f6 Panagiotis Kanavos
                throw new ArgumentException("rootPath must be an absolute path","rootPath");
128 5d7b20e8 Panagiotis Kanavos
            if (IdleTimeout == null)
129 5d7b20e8 Panagiotis Kanavos
                throw new InvalidOperationException("IdleTimeout must have a valid value");
130 4ec636f6 Panagiotis Kanavos
            Contract.EndContractBlock();
131 4ec636f6 Panagiotis Kanavos
132 4ec636f6 Panagiotis Kanavos
            AccountInfo = accountInfo;
133 4ec636f6 Panagiotis Kanavos
            RootPath = rootPath;
134 5d7b20e8 Panagiotis Kanavos
135 5d7b20e8 Panagiotis Kanavos
            _eventIdleBatch = new FileEventIdleBatch((int)IdleTimeout.TotalMilliseconds, ProcessBatchedEvents);
136 5d7b20e8 Panagiotis Kanavos
137 174bbb6e Panagiotis Kanavos
            _watcher = new FileSystemWatcher(rootPath) {IncludeSubdirectories = true,InternalBufferSize=8*4096};
138 78ebfd2d Panagiotis Kanavos
            _adapter = new FileSystemWatcherAdapter(_watcher);
139 78ebfd2d Panagiotis Kanavos
140 78ebfd2d Panagiotis Kanavos
            _adapter.Changed += OnFileEvent;
141 78ebfd2d Panagiotis Kanavos
            _adapter.Created += OnFileEvent;
142 78ebfd2d Panagiotis Kanavos
            _adapter.Deleted += OnFileEvent;
143 174bbb6e Panagiotis Kanavos
            //_adapter.Renamed += OnRenameEvent;
144 78ebfd2d Panagiotis Kanavos
            _adapter.Moved += OnMoveEvent;
145 4ec636f6 Panagiotis Kanavos
            _watcher.EnableRaisingEvents = true;
146 4ec636f6 Panagiotis Kanavos
147 4ec636f6 Panagiotis Kanavos
148 4ec636f6 Panagiotis Kanavos
            _agent = Agent<WorkflowState>.Start(inbox =>
149 4ec636f6 Panagiotis Kanavos
            {
150 4ec636f6 Panagiotis Kanavos
                Action loop = null;
151 4ec636f6 Panagiotis Kanavos
                loop = () =>
152 4ec636f6 Panagiotis Kanavos
                {
153 4ec636f6 Panagiotis Kanavos
                    var message = inbox.Receive();
154 139ac1e8 Panagiotis Kanavos
                    var process=message.Then(Process,inbox.CancellationToken);                    
155 4ec636f6 Panagiotis Kanavos
                    inbox.LoopAsync(process,loop,ex=>
156 4ec636f6 Panagiotis Kanavos
                        Log.ErrorFormat("[ERROR] File Event Processing:\r{0}", ex));
157 4ec636f6 Panagiotis Kanavos
                };
158 4ec636f6 Panagiotis Kanavos
                loop();
159 4ec636f6 Panagiotis Kanavos
            });
160 9c4346c9 Panagiotis Kanavos
        }
161 9c4346c9 Panagiotis Kanavos
162 4ec636f6 Panagiotis Kanavos
        private Task<object> Process(WorkflowState state)
163 a64c87c8 Panagiotis Kanavos
        {
164 4ec636f6 Panagiotis Kanavos
            if (state==null)
165 4ec636f6 Panagiotis Kanavos
                throw new ArgumentNullException("state");
166 4ec636f6 Panagiotis Kanavos
            Contract.EndContractBlock();
167 4ec636f6 Panagiotis Kanavos
168 4f6d51d4 Panagiotis Kanavos
            if (Ignore(state.Path))
169 4f6d51d4 Panagiotis Kanavos
                return CompletedTask<object>.Default;
170 4ec636f6 Panagiotis Kanavos
171 4ec636f6 Panagiotis Kanavos
            var networkState = NetworkGate.GetNetworkState(state.Path);
172 4ec636f6 Panagiotis Kanavos
            //Skip if the file is already being downloaded or uploaded and 
173 4ec636f6 Panagiotis Kanavos
            //the change is create or modify
174 4ec636f6 Panagiotis Kanavos
            if (networkState != NetworkOperation.None &&
175 4ec636f6 Panagiotis Kanavos
                (
176 4ec636f6 Panagiotis Kanavos
                    state.TriggeringChange == WatcherChangeTypes.Created ||
177 4ec636f6 Panagiotis Kanavos
                    state.TriggeringChange == WatcherChangeTypes.Changed
178 4ec636f6 Panagiotis Kanavos
                ))
179 4ec636f6 Panagiotis Kanavos
                return CompletedTask<object>.Default;
180 a64c87c8 Panagiotis Kanavos
181 a64c87c8 Panagiotis Kanavos
            try
182 a64c87c8 Panagiotis Kanavos
            {
183 174bbb6e Panagiotis Kanavos
                //StatusKeeper.EnsureFileState(state.Path);
184 174bbb6e Panagiotis Kanavos
                
185 4ec636f6 Panagiotis Kanavos
                UpdateFileStatus(state);
186 4ec636f6 Panagiotis Kanavos
                UpdateOverlayStatus(state);
187 4ec636f6 Panagiotis Kanavos
                UpdateFileChecksum(state);
188 4ec636f6 Panagiotis Kanavos
                WorkflowAgent.Post(state);
189 a64c87c8 Panagiotis Kanavos
            }
190 a64c87c8 Panagiotis Kanavos
            catch (IOException exc)
191 a64c87c8 Panagiotis Kanavos
            {
192 4ec636f6 Panagiotis Kanavos
                if (File.Exists(state.Path))
193 0af3141d Panagiotis Kanavos
                {
194 4ec636f6 Panagiotis Kanavos
                    Log.WarnFormat("File access error occured, retrying {0}\n{1}", state.Path, exc);
195 4ec636f6 Panagiotis Kanavos
                    _agent.Post(state);
196 0af3141d Panagiotis Kanavos
                }
197 0af3141d Panagiotis Kanavos
                else
198 0af3141d Panagiotis Kanavos
                {
199 4ec636f6 Panagiotis Kanavos
                    Log.WarnFormat("File {0} does not exist. Will be ignored\n{1}", state.Path, exc);
200 0af3141d Panagiotis Kanavos
                }
201 a64c87c8 Panagiotis Kanavos
            }
202 a64c87c8 Panagiotis Kanavos
            catch (Exception exc)
203 a64c87c8 Panagiotis Kanavos
            {
204 4ec636f6 Panagiotis Kanavos
                Log.WarnFormat("Error occured while indexing{0}. The file will be skipped\n{1}",
205 4ec636f6 Panagiotis Kanavos
                               state.Path, exc);
206 a64c87c8 Panagiotis Kanavos
            }
207 4ec636f6 Panagiotis Kanavos
            return CompletedTask<object>.Default;
208 5e31048f Panagiotis Kanavos
        }
209 a64c87c8 Panagiotis Kanavos
210 9c4346c9 Panagiotis Kanavos
        public bool Pause
211 9c4346c9 Panagiotis Kanavos
        {
212 9c4346c9 Panagiotis Kanavos
            get { return _watcher == null || !_watcher.EnableRaisingEvents; }
213 9c4346c9 Panagiotis Kanavos
            set
214 9c4346c9 Panagiotis Kanavos
            {
215 9c4346c9 Panagiotis Kanavos
                if (_watcher != null)
216 9c4346c9 Panagiotis Kanavos
                    _watcher.EnableRaisingEvents = !value;                
217 9c4346c9 Panagiotis Kanavos
            }
218 9c4346c9 Panagiotis Kanavos
        }
219 9c4346c9 Panagiotis Kanavos
220 77e10b4f Panagiotis Kanavos
        public string CachePath { get; set; }
221 1caef52e Panagiotis Kanavos
222 2341c603 pkanavos
        /*private List<string> _selectivePaths = new List<string>();
223 d3a13891 Panagiotis Kanavos
        public List<string> SelectivePaths
224 d3a13891 Panagiotis Kanavos
        {
225 d3a13891 Panagiotis Kanavos
            get { return _selectivePaths; }
226 d3a13891 Panagiotis Kanavos
            set { _selectivePaths = value; }
227 d3a13891 Panagiotis Kanavos
        }
228 2341c603 pkanavos
*/
229 2341c603 pkanavos
        public Selectives Selectives { get; set; }
230 d3a13891 Panagiotis Kanavos
231 d3a13891 Panagiotis Kanavos
232 9c4346c9 Panagiotis Kanavos
        public void Post(WorkflowState workflowState)
233 9c4346c9 Panagiotis Kanavos
        {
234 cfed7823 Panagiotis Kanavos
            if (workflowState == null)
235 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("workflowState");
236 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
237 cfed7823 Panagiotis Kanavos
238 9c4346c9 Panagiotis Kanavos
            _agent.Post(workflowState);
239 9c4346c9 Panagiotis Kanavos
        }
240 9c4346c9 Panagiotis Kanavos
241 9c4346c9 Panagiotis Kanavos
        public void Stop()
242 9c4346c9 Panagiotis Kanavos
        {
243 9c4346c9 Panagiotis Kanavos
            if (_watcher != null)
244 9c4346c9 Panagiotis Kanavos
            {
245 9c4346c9 Panagiotis Kanavos
                _watcher.Dispose();
246 9c4346c9 Panagiotis Kanavos
            }
247 9c4346c9 Panagiotis Kanavos
            _watcher = null;
248 9c4346c9 Panagiotis Kanavos
249 cfed7823 Panagiotis Kanavos
            if (_agent!=null)
250 4ec636f6 Panagiotis Kanavos
                _agent.Stop();
251 9c4346c9 Panagiotis Kanavos
        }
252 9c4346c9 Panagiotis Kanavos
253 1caef52e Panagiotis Kanavos
        // Enumerate all files in the Pithos directory except those in the Fragment folder
254 1caef52e Panagiotis Kanavos
        // and files with a .ignore extension
255 1caef52e Panagiotis Kanavos
        public IEnumerable<string> EnumerateFiles(string searchPattern="*")
256 1caef52e Panagiotis Kanavos
        {
257 1caef52e Panagiotis Kanavos
            var monitoredFiles = from filePath in Directory.EnumerateFileSystemEntries(RootPath, searchPattern, SearchOption.AllDirectories)
258 1caef52e Panagiotis Kanavos
                                 where !Ignore(filePath)
259 1caef52e Panagiotis Kanavos
                                 select filePath;
260 1caef52e Panagiotis Kanavos
            return monitoredFiles;
261 1caef52e Panagiotis Kanavos
        }
262 1caef52e Panagiotis Kanavos
263 1caef52e Panagiotis Kanavos
        public IEnumerable<FileInfo> EnumerateFileInfos(string searchPattern="*")
264 1caef52e Panagiotis Kanavos
        {
265 1caef52e Panagiotis Kanavos
            var rootDir = new DirectoryInfo(RootPath);
266 1caef52e Panagiotis Kanavos
            var monitoredFiles = from file in rootDir.EnumerateFiles(searchPattern, SearchOption.AllDirectories)
267 1caef52e Panagiotis Kanavos
                                 where !Ignore(file.FullName)
268 1caef52e Panagiotis Kanavos
                                 select file;
269 1caef52e Panagiotis Kanavos
            return monitoredFiles;
270 1caef52e Panagiotis Kanavos
        }                
271 1caef52e Panagiotis Kanavos
272 1caef52e Panagiotis Kanavos
        public IEnumerable<string> EnumerateFilesAsRelativeUrls(string searchPattern="*")
273 1caef52e Panagiotis Kanavos
        {
274 1caef52e Panagiotis Kanavos
            var rootDir = new DirectoryInfo(RootPath);
275 1caef52e Panagiotis Kanavos
            var monitoredFiles = from file in rootDir.EnumerateFiles(searchPattern, SearchOption.AllDirectories)
276 1caef52e Panagiotis Kanavos
                                 where !Ignore(file.FullName)
277 1caef52e Panagiotis Kanavos
                                 select file.AsRelativeUrlTo(RootPath);
278 1caef52e Panagiotis Kanavos
            return monitoredFiles;
279 1caef52e Panagiotis Kanavos
        }                
280 1caef52e Panagiotis Kanavos
281 540b8cf8 Panagiotis Kanavos
        public IEnumerable<string> EnumerateFilesSystemInfosAsRelativeUrls(string searchPattern="*")
282 540b8cf8 Panagiotis Kanavos
        {
283 540b8cf8 Panagiotis Kanavos
            var rootDir = new DirectoryInfo(RootPath);
284 540b8cf8 Panagiotis Kanavos
            var monitoredFiles = from file in rootDir.EnumerateFileSystemInfos(searchPattern, SearchOption.AllDirectories)
285 540b8cf8 Panagiotis Kanavos
                                 where !Ignore(file.FullName)
286 540b8cf8 Panagiotis Kanavos
                                 select file.AsRelativeUrlTo(RootPath);
287 540b8cf8 Panagiotis Kanavos
            return monitoredFiles;
288 540b8cf8 Panagiotis Kanavos
        }                
289 540b8cf8 Panagiotis Kanavos
290 1caef52e Panagiotis Kanavos
291 1caef52e Panagiotis Kanavos
        
292 1caef52e Panagiotis Kanavos
293 1caef52e Panagiotis Kanavos
        private bool Ignore(string filePath)
294 1caef52e Panagiotis Kanavos
        {
295 139ac1e8 Panagiotis Kanavos
            //Ignore all first-level directories and files (ie at the container folders level)
296 d9b1cbeb Panagiotis Kanavos
            if (FoundBelowRoot(filePath, RootPath,1))
297 139ac1e8 Panagiotis Kanavos
                return true;
298 d9b1cbeb Panagiotis Kanavos
299 139ac1e8 Panagiotis Kanavos
            //Ignore first-level items under the "others" folder (ie at the accounts folders level).
300 d9b1cbeb Panagiotis Kanavos
            var othersPath = Path.Combine(RootPath, FolderConstants.OthersFolder);
301 d9b1cbeb Panagiotis Kanavos
            if (FoundBelowRoot(filePath, othersPath,1))
302 139ac1e8 Panagiotis Kanavos
                return true;
303 d9b1cbeb Panagiotis Kanavos
304 139ac1e8 Panagiotis Kanavos
            //Ignore second-level (container) folders under the "others" folder (ie at the container folders level). 
305 d9b1cbeb Panagiotis Kanavos
            if (FoundBelowRoot(filePath, othersPath,2))
306 d9b1cbeb Panagiotis Kanavos
                return true;            
307 d9b1cbeb Panagiotis Kanavos
308 d9b1cbeb Panagiotis Kanavos
309 d9b1cbeb Panagiotis Kanavos
            //Ignore anything happening in the cache path
310 77e10b4f Panagiotis Kanavos
            if (filePath.StartsWith(CachePath))
311 1caef52e Panagiotis Kanavos
                return true;
312 0af3141d Panagiotis Kanavos
            if (_ignoreFiles.ContainsKey(filePath.ToLower()))
313 0af3141d Panagiotis Kanavos
                return true;
314 139ac1e8 Panagiotis Kanavos
315 fec5da06 Panagiotis Kanavos
            //Ignore if selective synchronization is defined, 
316 fec5da06 Panagiotis Kanavos
                //And the target file is not below any of the selective paths
317 2341c603 pkanavos
            return !Selectives.IsSelected(AccountInfo, filePath);
318 1caef52e Panagiotis Kanavos
        }
319 1caef52e Panagiotis Kanavos
320 d9b1cbeb Panagiotis Kanavos
/*        private static bool FoundInRoot(string filePath, string rootPath)
321 d9b1cbeb Panagiotis Kanavos
        {
322 d9b1cbeb Panagiotis Kanavos
            //var rootDirectory = new DirectoryInfo(rootPath);
323 d9b1cbeb Panagiotis Kanavos
324 d9b1cbeb Panagiotis Kanavos
            //If the paths are equal, return true
325 d9b1cbeb Panagiotis Kanavos
            if (filePath.Equals(rootPath, StringComparison.InvariantCultureIgnoreCase))
326 d9b1cbeb Panagiotis Kanavos
                return true;
327 d9b1cbeb Panagiotis Kanavos
328 d9b1cbeb Panagiotis Kanavos
            //If the filepath is below the root path
329 d9b1cbeb Panagiotis Kanavos
            if (filePath.StartsWith(rootPath,StringComparison.InvariantCulture))
330 d9b1cbeb Panagiotis Kanavos
            {
331 d9b1cbeb Panagiotis Kanavos
                //Get the relative path
332 d9b1cbeb Panagiotis Kanavos
                var relativePath = filePath.Substring(rootPath.Length + 1);
333 d9b1cbeb Panagiotis Kanavos
                //If the relativePath does NOT contains a path separator, we found a match
334 d9b1cbeb Panagiotis Kanavos
                return (!relativePath.Contains(@"\"));
335 d9b1cbeb Panagiotis Kanavos
            }
336 d9b1cbeb Panagiotis Kanavos
337 d9b1cbeb Panagiotis Kanavos
            //If the filepath is not under the root path, return false
338 d9b1cbeb Panagiotis Kanavos
            return false;            
339 d9b1cbeb Panagiotis Kanavos
        }*/
340 d9b1cbeb Panagiotis Kanavos
341 d9b1cbeb Panagiotis Kanavos
342 d9b1cbeb Panagiotis Kanavos
        private static bool FoundBelowRoot(string filePath, string rootPath,int level)
343 d9b1cbeb Panagiotis Kanavos
        {
344 d9b1cbeb Panagiotis Kanavos
            //var rootDirectory = new DirectoryInfo(rootPath);
345 d9b1cbeb Panagiotis Kanavos
346 d9b1cbeb Panagiotis Kanavos
            //If the paths are equal, return true
347 d9b1cbeb Panagiotis Kanavos
            if (filePath.Equals(rootPath, StringComparison.InvariantCultureIgnoreCase))
348 d9b1cbeb Panagiotis Kanavos
                return true;
349 d9b1cbeb Panagiotis Kanavos
350 d9b1cbeb Panagiotis Kanavos
            //If the filepath is below the root path
351 d9b1cbeb Panagiotis Kanavos
            if (filePath.StartsWith(rootPath,StringComparison.InvariantCulture))
352 d9b1cbeb Panagiotis Kanavos
            {
353 d9b1cbeb Panagiotis Kanavos
                //Get the relative path
354 d9b1cbeb Panagiotis Kanavos
                var relativePath = filePath.Substring(rootPath.Length + 1);
355 d9b1cbeb Panagiotis Kanavos
                //If the relativePath does NOT contains a path separator, we found a match
356 d9b1cbeb Panagiotis Kanavos
                var levels=relativePath.ToCharArray().Count(c=>c=='\\')+1;                
357 d9b1cbeb Panagiotis Kanavos
                return levels==level;
358 d9b1cbeb Panagiotis Kanavos
            }
359 d9b1cbeb Panagiotis Kanavos
360 d9b1cbeb Panagiotis Kanavos
            //If the filepath is not under the root path, return false
361 d9b1cbeb Panagiotis Kanavos
            return false;            
362 d9b1cbeb Panagiotis Kanavos
        }
363 d9b1cbeb Panagiotis Kanavos
364 1caef52e Panagiotis Kanavos
        //Post a Change message for all events except rename
365 9c4346c9 Panagiotis Kanavos
        void OnFileEvent(object sender, FileSystemEventArgs e)
366 9c4346c9 Panagiotis Kanavos
        {
367 77e10b4f Panagiotis Kanavos
            //Ignore events that affect the cache folder
368 1caef52e Panagiotis Kanavos
            var filePath = e.FullPath;
369 1caef52e Panagiotis Kanavos
            if (Ignore(filePath)) 
370 a0dcfcc9 Panagiotis Kanavos
                return;
371 79f92570 Panagiotis Kanavos
            _eventIdleBatch.Post(e);
372 9c4346c9 Panagiotis Kanavos
        }
373 9c4346c9 Panagiotis Kanavos
374 1caef52e Panagiotis Kanavos
375 174bbb6e Panagiotis Kanavos
/*
376 1caef52e Panagiotis Kanavos
        //Post a Change message for renames containing the old and new names
377 9c4346c9 Panagiotis Kanavos
        void OnRenameEvent(object sender, RenamedEventArgs e)
378 9c4346c9 Panagiotis Kanavos
        {
379 1caef52e Panagiotis Kanavos
            var oldFullPath = e.OldFullPath;
380 1caef52e Panagiotis Kanavos
            var fullPath = e.FullPath;
381 1caef52e Panagiotis Kanavos
            if (Ignore(oldFullPath) || Ignore(fullPath))
382 1caef52e Panagiotis Kanavos
                return;
383 1caef52e Panagiotis Kanavos
384 1bfc38f1 Panagiotis Kanavos
            _agent.Post(new WorkflowState
385 9c4346c9 Panagiotis Kanavos
            {
386 1bfc38f1 Panagiotis Kanavos
                AccountInfo=AccountInfo,
387 1caef52e Panagiotis Kanavos
                OldPath = oldFullPath,
388 9c4346c9 Panagiotis Kanavos
                OldFileName = e.OldName,
389 1caef52e Panagiotis Kanavos
                Path = fullPath,
390 9c4346c9 Panagiotis Kanavos
                FileName = e.Name,
391 78ebfd2d Panagiotis Kanavos
                TriggeringChange = e.ChangeType
392 78ebfd2d Panagiotis Kanavos
            });
393 78ebfd2d Panagiotis Kanavos
        }
394 174bbb6e Panagiotis Kanavos
*/
395 78ebfd2d Panagiotis Kanavos
396 174bbb6e Panagiotis Kanavos
        //Post a Change message for moves containing the old and new names
397 78ebfd2d Panagiotis Kanavos
        void OnMoveEvent(object sender, MovedEventArgs e)
398 78ebfd2d Panagiotis Kanavos
        {
399 78ebfd2d Panagiotis Kanavos
            var oldFullPath = e.OldFullPath;
400 78ebfd2d Panagiotis Kanavos
            var fullPath = e.FullPath;
401 78ebfd2d Panagiotis Kanavos
            if (Ignore(oldFullPath) || Ignore(fullPath))
402 78ebfd2d Panagiotis Kanavos
                return;
403 78ebfd2d Panagiotis Kanavos
404 79f92570 Panagiotis Kanavos
            _eventIdleBatch.Post(e);
405 9c4346c9 Panagiotis Kanavos
        }
406 9c4346c9 Panagiotis Kanavos
407 9c4346c9 Panagiotis Kanavos
408 9c4346c9 Panagiotis Kanavos
409 9c4346c9 Panagiotis Kanavos
        private Dictionary<WatcherChangeTypes, FileStatus> _statusDict = new Dictionary<WatcherChangeTypes, FileStatus>
410 fbbbe99b Panagiotis Kanavos
                                                                             {
411 9c4346c9 Panagiotis Kanavos
            {WatcherChangeTypes.Created,FileStatus.Created},
412 9c4346c9 Panagiotis Kanavos
            {WatcherChangeTypes.Changed,FileStatus.Modified},
413 9c4346c9 Panagiotis Kanavos
            {WatcherChangeTypes.Deleted,FileStatus.Deleted},
414 9c4346c9 Panagiotis Kanavos
            {WatcherChangeTypes.Renamed,FileStatus.Renamed}
415 9c4346c9 Panagiotis Kanavos
        };
416 9c4346c9 Panagiotis Kanavos
417 fbbbe99b Panagiotis Kanavos
        private Dictionary<string, string> _ignoreFiles=new Dictionary<string, string>();
418 0af3141d Panagiotis Kanavos
419 9c4346c9 Panagiotis Kanavos
        private WorkflowState UpdateFileStatus(WorkflowState state)
420 9c4346c9 Panagiotis Kanavos
        {
421 cfed7823 Panagiotis Kanavos
            if (state==null)
422 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("state");
423 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(state.Path))
424 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The state's Path can't be empty","state");
425 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
426 1caef52e Panagiotis Kanavos
427 cfed7823 Panagiotis Kanavos
            var path = state.Path;
428 cfed7823 Panagiotis Kanavos
            var status = _statusDict[state.TriggeringChange];
429 9c4346c9 Panagiotis Kanavos
            var oldStatus = Workflow.StatusKeeper.GetFileStatus(path);
430 9c4346c9 Panagiotis Kanavos
            if (status == oldStatus)
431 9c4346c9 Panagiotis Kanavos
            {
432 9c4346c9 Panagiotis Kanavos
                state.Status = status;
433 9c4346c9 Panagiotis Kanavos
                state.Skip = true;
434 9c4346c9 Panagiotis Kanavos
                return state;
435 9c4346c9 Panagiotis Kanavos
            }
436 9c4346c9 Panagiotis Kanavos
            if (state.Status == FileStatus.Renamed)
437 9c4346c9 Panagiotis Kanavos
                Workflow.ClearFileStatus(path);
438 9c4346c9 Panagiotis Kanavos
439 9c4346c9 Panagiotis Kanavos
            state.Status = Workflow.SetFileStatus(path, status);
440 9c4346c9 Panagiotis Kanavos
            return state;
441 9c4346c9 Panagiotis Kanavos
        }
442 9c4346c9 Panagiotis Kanavos
443 9c4346c9 Panagiotis Kanavos
        private WorkflowState UpdateOverlayStatus(WorkflowState state)
444 9c4346c9 Panagiotis Kanavos
        {
445 cfed7823 Panagiotis Kanavos
            if (state==null)
446 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("state");
447 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
448 cfed7823 Panagiotis Kanavos
449 9c4346c9 Panagiotis Kanavos
            if (state.Skip)
450 9c4346c9 Panagiotis Kanavos
                return state;
451 9c4346c9 Panagiotis Kanavos
452 9c4346c9 Panagiotis Kanavos
            switch (state.Status)
453 9c4346c9 Panagiotis Kanavos
            {
454 9c4346c9 Panagiotis Kanavos
                case FileStatus.Created:
455 174bbb6e Panagiotis Kanavos
                    this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified,state.ShortHash);
456 174bbb6e Panagiotis Kanavos
                    break;
457 9c4346c9 Panagiotis Kanavos
                case FileStatus.Modified:
458 174bbb6e Panagiotis Kanavos
                    this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified,state.ShortHash);
459 9c4346c9 Panagiotis Kanavos
                    break;
460 9c4346c9 Panagiotis Kanavos
                case FileStatus.Deleted:
461 cfed7823 Panagiotis Kanavos
                    //this.StatusAgent.RemoveFileOverlayStatus(state.Path);
462 9c4346c9 Panagiotis Kanavos
                    break;
463 9c4346c9 Panagiotis Kanavos
                case FileStatus.Renamed:
464 cfed7823 Panagiotis Kanavos
                    this.StatusKeeper.ClearFileStatus(state.OldPath);
465 174bbb6e Panagiotis Kanavos
                    this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified,state.ShortHash);
466 9c4346c9 Panagiotis Kanavos
                    break;
467 9c4346c9 Panagiotis Kanavos
                case FileStatus.Unchanged:
468 174bbb6e Panagiotis Kanavos
                    this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Normal,state.ShortHash);
469 9c4346c9 Panagiotis Kanavos
                    break;
470 9c4346c9 Panagiotis Kanavos
            }
471 9c4346c9 Panagiotis Kanavos
472 9c4346c9 Panagiotis Kanavos
            if (state.Status == FileStatus.Deleted)
473 1caef52e Panagiotis Kanavos
                NativeMethods.RaiseChangeNotification(Path.GetDirectoryName(state.Path));
474 9c4346c9 Panagiotis Kanavos
            else
475 1caef52e Panagiotis Kanavos
                NativeMethods.RaiseChangeNotification(state.Path);
476 9c4346c9 Panagiotis Kanavos
            return state;
477 9c4346c9 Panagiotis Kanavos
        }
478 9c4346c9 Panagiotis Kanavos
479 9c4346c9 Panagiotis Kanavos
480 9c4346c9 Panagiotis Kanavos
        private WorkflowState UpdateFileChecksum(WorkflowState state)
481 9c4346c9 Panagiotis Kanavos
        {
482 9c4346c9 Panagiotis Kanavos
            if (state.Skip)
483 9c4346c9 Panagiotis Kanavos
                return state;
484 9c4346c9 Panagiotis Kanavos
485 9c4346c9 Panagiotis Kanavos
            if (state.Status == FileStatus.Deleted)
486 9c4346c9 Panagiotis Kanavos
                return state;
487 9c4346c9 Panagiotis Kanavos
488 1caef52e Panagiotis Kanavos
            var path = state.Path;
489 1caef52e Panagiotis Kanavos
            //Skip calculation for folders
490 1caef52e Panagiotis Kanavos
            if (Directory.Exists(path))
491 1caef52e Panagiotis Kanavos
                return state;
492 1caef52e Panagiotis Kanavos
493 0af3141d Panagiotis Kanavos
            var info = new FileInfo(path);
494 174bbb6e Panagiotis Kanavos
495 f4a72cb8 pkanavos
            using (StatusNotification.GetNotifier("Hashing {0}", "Finished Hashing {0}", info.Name))
496 f4a72cb8 pkanavos
            {
497 f4a72cb8 pkanavos
498 f4a72cb8 pkanavos
                var shortHash = info.ComputeShortHash();
499 9c4346c9 Panagiotis Kanavos
500 f4a72cb8 pkanavos
                string merkleHash = info.CalculateHash(StatusKeeper.BlockSize, StatusKeeper.BlockHash);
501 f4a72cb8 pkanavos
                StatusKeeper.UpdateFileChecksum(path, shortHash, merkleHash);
502 f4a72cb8 pkanavos
503 f4a72cb8 pkanavos
                state.Hash = merkleHash;
504 f4a72cb8 pkanavos
                return state;
505 f4a72cb8 pkanavos
            }
506 9c4346c9 Panagiotis Kanavos
        }
507 9c4346c9 Panagiotis Kanavos
508 bfc13ed8 Panagiotis Kanavos
        //Does the file exist in the container's local folder?
509 bfc13ed8 Panagiotis Kanavos
        public bool Exists(string relativePath)
510 bfc13ed8 Panagiotis Kanavos
        {
511 bfc13ed8 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(relativePath))
512 bfc13ed8 Panagiotis Kanavos
                throw new ArgumentNullException("relativePath");
513 bfc13ed8 Panagiotis Kanavos
            //A RootPath must be set before calling this method
514 bfc13ed8 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(RootPath))
515 bfc13ed8 Panagiotis Kanavos
                throw new InvalidOperationException("RootPath was not set");
516 bfc13ed8 Panagiotis Kanavos
            Contract.EndContractBlock();
517 bfc13ed8 Panagiotis Kanavos
            //Create the absolute path by combining the RootPath with the relativePath
518 bfc13ed8 Panagiotis Kanavos
            var absolutePath=Path.Combine(RootPath, relativePath);
519 bfc13ed8 Panagiotis Kanavos
            //Is this a valid file?
520 bfc13ed8 Panagiotis Kanavos
            if (File.Exists(absolutePath))
521 bfc13ed8 Panagiotis Kanavos
                return true;
522 bfc13ed8 Panagiotis Kanavos
            //Or a directory?
523 a64c87c8 Panagiotis Kanavos
            if (Directory.Exists(absolutePath))
524 bfc13ed8 Panagiotis Kanavos
                return true;
525 bfc13ed8 Panagiotis Kanavos
            //Fail if it is neither
526 bfc13ed8 Panagiotis Kanavos
            return false;
527 bfc13ed8 Panagiotis Kanavos
        }
528 9c4346c9 Panagiotis Kanavos
529 fbbbe99b Panagiotis Kanavos
        public static FileAgent GetFileAgent(AccountInfo accountInfo)
530 fbbbe99b Panagiotis Kanavos
        {
531 fbbbe99b Panagiotis Kanavos
            return GetFileAgent(accountInfo.AccountPath);
532 fbbbe99b Panagiotis Kanavos
        }
533 fbbbe99b Panagiotis Kanavos
534 fbbbe99b Panagiotis Kanavos
        public static FileAgent GetFileAgent(string rootPath)
535 fbbbe99b Panagiotis Kanavos
        {
536 fbbbe99b Panagiotis Kanavos
            return AgentLocator<FileAgent>.Get(rootPath.ToLower());
537 fbbbe99b Panagiotis Kanavos
        }
538 fbbbe99b Panagiotis Kanavos
539 fbbbe99b Panagiotis Kanavos
540 f3d080df Panagiotis Kanavos
        public FileSystemInfo GetFileSystemInfo(string relativePath)
541 bfc13ed8 Panagiotis Kanavos
        {
542 bfc13ed8 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(relativePath))
543 bfc13ed8 Panagiotis Kanavos
                throw new ArgumentNullException("relativePath");
544 bfc13ed8 Panagiotis Kanavos
            //A RootPath must be set before calling this method
545 bfc13ed8 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(RootPath))
546 bfc13ed8 Panagiotis Kanavos
                throw new InvalidOperationException("RootPath was not set");            
547 bfc13ed8 Panagiotis Kanavos
            Contract.EndContractBlock();            
548 bfc13ed8 Panagiotis Kanavos
549 bfc13ed8 Panagiotis Kanavos
            var absolutePath = Path.Combine(RootPath, relativePath);
550 bfc13ed8 Panagiotis Kanavos
551 4f6d51d4 Panagiotis Kanavos
            if (Directory.Exists(absolutePath))
552 f3d080df Panagiotis Kanavos
                return new DirectoryInfo(absolutePath).WithProperCapitalization();
553 4f6d51d4 Panagiotis Kanavos
            else
554 f3d080df Panagiotis Kanavos
                return new FileInfo(absolutePath).WithProperCapitalization();
555 bfc13ed8 Panagiotis Kanavos
            
556 bfc13ed8 Panagiotis Kanavos
        }
557 a27aa447 Panagiotis Kanavos
558 0af3141d Panagiotis Kanavos
        public void Delete(string relativePath)
559 0af3141d Panagiotis Kanavos
        {
560 4f6d51d4 Panagiotis Kanavos
            var absolutePath = Path.Combine(RootPath, relativePath).ToLower();
561 81c5c310 pkanavos
            if (Log.IsDebugEnabled)
562 81c5c310 pkanavos
                Log.DebugFormat("Deleting {0}", absolutePath);
563 0af3141d Panagiotis Kanavos
            if (File.Exists(absolutePath))
564 4f6d51d4 Panagiotis Kanavos
            {    
565 4f6d51d4 Panagiotis Kanavos
                try
566 4f6d51d4 Panagiotis Kanavos
                {
567 4f6d51d4 Panagiotis Kanavos
                    File.Delete(absolutePath);
568 4f6d51d4 Panagiotis Kanavos
                }
569 4f6d51d4 Panagiotis Kanavos
                //The file may have been deleted by another thread. Just ignore the relevant exception
570 4f6d51d4 Panagiotis Kanavos
                catch (FileNotFoundException) { }
571 4f6d51d4 Panagiotis Kanavos
            }
572 4f6d51d4 Panagiotis Kanavos
            else if (Directory.Exists(absolutePath))
573 4f6d51d4 Panagiotis Kanavos
            {
574 4f6d51d4 Panagiotis Kanavos
                try
575 4f6d51d4 Panagiotis Kanavos
                {
576 4f6d51d4 Panagiotis Kanavos
                    Directory.Delete(absolutePath, true);
577 4f6d51d4 Panagiotis Kanavos
                }
578 4f6d51d4 Panagiotis Kanavos
                //The directory may have been deleted by another thread. Just ignore the relevant exception
579 4f6d51d4 Panagiotis Kanavos
                catch (DirectoryNotFoundException){}                
580 0af3141d Panagiotis Kanavos
            }
581 4f6d51d4 Panagiotis Kanavos
        
582 4f6d51d4 Panagiotis Kanavos
            //_ignoreFiles[absolutePath] = absolutePath;                
583 0af3141d Panagiotis Kanavos
            StatusKeeper.ClearFileStatus(absolutePath);
584 0af3141d Panagiotis Kanavos
        }
585 9c4346c9 Panagiotis Kanavos
    }
586 9c4346c9 Panagiotis Kanavos
}