Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / PithosMonitor.cs @ 79f92570

History | View | Annotate | Download (20.7 kB)

1 255f5f86 Panagiotis Kanavos
#region
2 255f5f86 Panagiotis Kanavos
/* -----------------------------------------------------------------------
3 255f5f86 Panagiotis Kanavos
 * <copyright file="PithosMonitor.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 d78cbf09 Panagiotis Kanavos
using System;
43 d78cbf09 Panagiotis Kanavos
using System.Collections.Generic;
44 d78cbf09 Panagiotis Kanavos
using System.ComponentModel.Composition;
45 d78cbf09 Panagiotis Kanavos
using System.Diagnostics.Contracts;
46 d78cbf09 Panagiotis Kanavos
using System.IO;
47 d78cbf09 Panagiotis Kanavos
using System.Linq;
48 db8a9589 Panagiotis Kanavos
using System.Reflection;
49 d78cbf09 Panagiotis Kanavos
using System.Threading;
50 d78cbf09 Panagiotis Kanavos
using System.Threading.Tasks;
51 9c4346c9 Panagiotis Kanavos
using Pithos.Core.Agents;
52 d78cbf09 Panagiotis Kanavos
using Pithos.Interfaces;
53 5ce54458 Panagiotis Kanavos
using Pithos.Network;
54 5120f3cb Panagiotis Kanavos
using log4net;
55 d78cbf09 Panagiotis Kanavos
56 d78cbf09 Panagiotis Kanavos
namespace Pithos.Core
57 d78cbf09 Panagiotis Kanavos
{
58 d78cbf09 Panagiotis Kanavos
    [Export(typeof(PithosMonitor))]
59 d78cbf09 Panagiotis Kanavos
    public class PithosMonitor:IDisposable
60 d78cbf09 Panagiotis Kanavos
    {
61 db8a9589 Panagiotis Kanavos
        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 db8a9589 Panagiotis Kanavos
63 5ce54458 Panagiotis Kanavos
        private int _blockSize;
64 5ce54458 Panagiotis Kanavos
        private string _blockHash;
65 5ce54458 Panagiotis Kanavos
66 d78cbf09 Panagiotis Kanavos
        [Import]
67 d78cbf09 Panagiotis Kanavos
        public IPithosSettings Settings{get;set;}
68 d78cbf09 Panagiotis Kanavos
69 4ec636f6 Panagiotis Kanavos
        private IStatusKeeper _statusKeeper;
70 4ec636f6 Panagiotis Kanavos
71 d78cbf09 Panagiotis Kanavos
        [Import]
72 4ec636f6 Panagiotis Kanavos
        public IStatusKeeper StatusKeeper
73 4ec636f6 Panagiotis Kanavos
        {
74 4ec636f6 Panagiotis Kanavos
            get { return _statusKeeper; }
75 4ec636f6 Panagiotis Kanavos
            set
76 4ec636f6 Panagiotis Kanavos
            {
77 4ec636f6 Panagiotis Kanavos
                _statusKeeper = value;
78 4ec636f6 Panagiotis Kanavos
                FileAgent.StatusKeeper = value;
79 4ec636f6 Panagiotis Kanavos
            }
80 4ec636f6 Panagiotis Kanavos
        }
81 4ec636f6 Panagiotis Kanavos
82 4ec636f6 Panagiotis Kanavos
83 4ec636f6 Panagiotis Kanavos
        private IPithosWorkflow _workflow;
84 d78cbf09 Panagiotis Kanavos
85 d78cbf09 Panagiotis Kanavos
        [Import]
86 4ec636f6 Panagiotis Kanavos
        public IPithosWorkflow Workflow
87 4ec636f6 Panagiotis Kanavos
        {
88 4ec636f6 Panagiotis Kanavos
            get { return _workflow; }
89 4ec636f6 Panagiotis Kanavos
            set
90 4ec636f6 Panagiotis Kanavos
            {
91 4ec636f6 Panagiotis Kanavos
                _workflow = value;
92 4ec636f6 Panagiotis Kanavos
                FileAgent.Workflow = value;
93 4ec636f6 Panagiotis Kanavos
            }
94 4ec636f6 Panagiotis Kanavos
        }
95 d78cbf09 Panagiotis Kanavos
96 d78cbf09 Panagiotis Kanavos
        public ICloudClient CloudClient { get; set; }
97 d78cbf09 Panagiotis Kanavos
98 0c02aa65 Panagiotis Kanavos
        public IStatusNotification StatusNotification { get; set; }
99 0c02aa65 Panagiotis Kanavos
100 4ec636f6 Panagiotis Kanavos
        //[Import]
101 4ec636f6 Panagiotis Kanavos
        public FileAgent FileAgent { get; private set; }
102 4ec636f6 Panagiotis Kanavos
103 4ec636f6 Panagiotis Kanavos
        private WorkflowAgent _workflowAgent;
104 4ec636f6 Panagiotis Kanavos
105 9c4346c9 Panagiotis Kanavos
        [Import]
106 4ec636f6 Panagiotis Kanavos
        public WorkflowAgent WorkflowAgent
107 4ec636f6 Panagiotis Kanavos
        {
108 4ec636f6 Panagiotis Kanavos
            get { return _workflowAgent; }
109 4ec636f6 Panagiotis Kanavos
            set
110 4ec636f6 Panagiotis Kanavos
            {
111 4ec636f6 Panagiotis Kanavos
                _workflowAgent = value;
112 4ec636f6 Panagiotis Kanavos
                FileAgent.WorkflowAgent = value;
113 4ec636f6 Panagiotis Kanavos
            }
114 4ec636f6 Panagiotis Kanavos
        }
115 9c4346c9 Panagiotis Kanavos
        
116 9c4346c9 Panagiotis Kanavos
        [Import]
117 aa7ac00e Panagiotis Kanavos
        public NetworkAgent NetworkAgent { get; set; }
118 aa7ac00e Panagiotis Kanavos
        [Import]
119 aa7ac00e Panagiotis Kanavos
        public PollAgent PollAgent { get; set; }       
120 9c4346c9 Panagiotis Kanavos
121 0eea575a Panagiotis Kanavos
        public string UserName { get; set; }
122 c92e02f3 Panagiotis Kanavos
        private string _apiKey;
123 c92e02f3 Panagiotis Kanavos
        public string ApiKey
124 c92e02f3 Panagiotis Kanavos
        {
125 c92e02f3 Panagiotis Kanavos
            get { return _apiKey; }
126 c92e02f3 Panagiotis Kanavos
            set
127 c92e02f3 Panagiotis Kanavos
            {
128 c92e02f3 Panagiotis Kanavos
                _apiKey = value;
129 c92e02f3 Panagiotis Kanavos
                if (_accountInfo != null)
130 c92e02f3 Panagiotis Kanavos
                    _accountInfo.Token = value;
131 c92e02f3 Panagiotis Kanavos
            }
132 c92e02f3 Panagiotis Kanavos
        }
133 0eea575a Panagiotis Kanavos
134 0bd56b7c Panagiotis Kanavos
        private AccountInfo _accountInfo;
135 c53aa229 Panagiotis Kanavos
136 eeee29e3 Panagiotis Kanavos
137 db8a9589 Panagiotis Kanavos
138 db8a9589 Panagiotis Kanavos
139 5120f3cb Panagiotis Kanavos
140 d78cbf09 Panagiotis Kanavos
141 d78cbf09 Panagiotis Kanavos
        public bool Pause
142 d78cbf09 Panagiotis Kanavos
        {
143 5ce54458 Panagiotis Kanavos
            get { return FileAgent.Pause; }
144 d78cbf09 Panagiotis Kanavos
            set
145 d78cbf09 Panagiotis Kanavos
            {
146 5ce54458 Panagiotis Kanavos
                FileAgent.Pause = value;
147 d78cbf09 Panagiotis Kanavos
            }
148 d78cbf09 Panagiotis Kanavos
        }
149 d78cbf09 Panagiotis Kanavos
150 c28a075a Panagiotis Kanavos
        private string _rootPath;
151 c28a075a Panagiotis Kanavos
        public string RootPath
152 c28a075a Panagiotis Kanavos
        {
153 c28a075a Panagiotis Kanavos
            get { return _rootPath; }
154 7e26c075 Panagiotis Kanavos
            set 
155 c28a075a Panagiotis Kanavos
            {
156 7e26c075 Panagiotis Kanavos
                _rootPath = String.IsNullOrWhiteSpace(value) 
157 7e26c075 Panagiotis Kanavos
                    ? String.Empty 
158 7e26c075 Panagiotis Kanavos
                    : value.ToLower();
159 c28a075a Panagiotis Kanavos
            }
160 c28a075a Panagiotis Kanavos
        }
161 0eea575a Panagiotis Kanavos
162 d78cbf09 Panagiotis Kanavos
163 d78cbf09 Panagiotis Kanavos
        CancellationTokenSource _cancellationSource;
164 d78cbf09 Panagiotis Kanavos
165 4ec636f6 Panagiotis Kanavos
        public PithosMonitor()
166 4ec636f6 Panagiotis Kanavos
        {
167 79f92570 Panagiotis Kanavos
            FileAgent = new FileAgent(5000);
168 d78cbf09 Panagiotis Kanavos
169 4ec636f6 Panagiotis Kanavos
        }
170 7e26c075 Panagiotis Kanavos
        private bool _started;
171 d78cbf09 Panagiotis Kanavos
172 d78cbf09 Panagiotis Kanavos
        public void Start()
173 c53aa229 Panagiotis Kanavos
        {            
174 c53aa229 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(ApiKey))
175 c53aa229 Panagiotis Kanavos
                throw new InvalidOperationException("The ApiKey is empty");
176 c53aa229 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(UserName))
177 c53aa229 Panagiotis Kanavos
                throw new InvalidOperationException("The UserName is empty");
178 c53aa229 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(AuthenticationUrl))
179 c53aa229 Panagiotis Kanavos
                throw new InvalidOperationException("The Authentication url is empty");
180 c53aa229 Panagiotis Kanavos
            Contract.EndContractBlock();
181 c53aa229 Panagiotis Kanavos
182 437abfca Panagiotis Kanavos
            //If the account doesn't have a valid path, don't start monitoring but don't throw either
183 437abfca Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(RootPath))
184 437abfca Panagiotis Kanavos
                //TODO; Warn user?
185 437abfca Panagiotis Kanavos
                return;
186 437abfca Panagiotis Kanavos
187 70f12b36 Panagiotis Kanavos
            WorkflowAgent.StatusNotification = StatusNotification;
188 70f12b36 Panagiotis Kanavos
189 0c02aa65 Panagiotis Kanavos
            StatusNotification.NotifyChange("Starting");
190 7e26c075 Panagiotis Kanavos
            if (_started)
191 d78cbf09 Panagiotis Kanavos
            {
192 d78cbf09 Panagiotis Kanavos
                if (!_cancellationSource.IsCancellationRequested)
193 d78cbf09 Panagiotis Kanavos
                    return;
194 d78cbf09 Panagiotis Kanavos
            }
195 29672672 Panagiotis Kanavos
            _cancellationSource = new CancellationTokenSource();
196 d78cbf09 Panagiotis Kanavos
197 c636df1f Panagiotis Kanavos
198 c636df1f Panagiotis Kanavos
            CloudClient = new CloudFilesClient(UserName, ApiKey)
199 c636df1f Panagiotis Kanavos
                              {UsePithos = true, AuthenticationUrl = AuthenticationUrl};
200 c636df1f Panagiotis Kanavos
201 c53aa229 Panagiotis Kanavos
202 23821bd2 Panagiotis Kanavos
            _accountInfo = CloudClient.Authenticate();            
203 23821bd2 Panagiotis Kanavos
            _accountInfo.SiteUri = AuthenticationUrl;
204 c53aa229 Panagiotis Kanavos
            _accountInfo.AccountPath = RootPath;
205 c53aa229 Panagiotis Kanavos
206 5750d7cc Panagiotis Kanavos
207 5750d7cc Panagiotis Kanavos
            var pithosFolder = Path.Combine(RootPath, FolderConstants.PithosContainer);
208 5750d7cc Panagiotis Kanavos
            if (!Directory.Exists(pithosFolder))
209 5750d7cc Panagiotis Kanavos
                Directory.CreateDirectory(pithosFolder);
210 77e10b4f Panagiotis Kanavos
            //Create the cache folder and ensure it is hidden
211 77e10b4f Panagiotis Kanavos
            CreateHiddenFolder(RootPath, FolderConstants.CacheFolder);
212 77e10b4f Panagiotis Kanavos
213 0bd56b7c Panagiotis Kanavos
            var policy=CloudClient.GetAccountPolicies(_accountInfo);
214 c53aa229 Panagiotis Kanavos
215 0bd56b7c Panagiotis Kanavos
            StatusNotification.NotifyAccount(policy);
216 3c43ec9b Panagiotis Kanavos
            EnsurePithosContainers();
217 9c4346c9 Panagiotis Kanavos
            
218 5ce54458 Panagiotis Kanavos
            StatusKeeper.BlockHash = _blockHash;
219 5ce54458 Panagiotis Kanavos
            StatusKeeper.BlockSize = _blockSize;
220 9c4346c9 Panagiotis Kanavos
            
221 3c43ec9b Panagiotis Kanavos
            StatusKeeper.StartProcessing(_cancellationSource.Token);
222 c28a075a Panagiotis Kanavos
            IndexLocalFiles();
223 759bd3c4 Panagiotis Kanavos
            //Extract the URIs from the string collection
224 759bd3c4 Panagiotis Kanavos
            var settings = Settings.Accounts.First(s => s.AccountName == _accountInfo.UserName);
225 fec5da06 Panagiotis Kanavos
            var selectiveUrls=settings.SelectiveFolders.Cast<string>().Select(url => new Uri(url)).ToArray();
226 759bd3c4 Panagiotis Kanavos
227 759bd3c4 Panagiotis Kanavos
            SetSelectivePaths(selectiveUrls,null,null);
228 759bd3c4 Panagiotis Kanavos
            
229 c28a075a Panagiotis Kanavos
            StartWatcherAgent();
230 c53aa229 Panagiotis Kanavos
231 c53aa229 Panagiotis Kanavos
            StartNetworkAgent();
232 70f12b36 Panagiotis Kanavos
            
233 c92e02f3 Panagiotis Kanavos
            WorkflowAgent.RestartInterruptedFiles(_accountInfo);
234 c92e02f3 Panagiotis Kanavos
            _started = true;
235 29672672 Panagiotis Kanavos
        }
236 29672672 Panagiotis Kanavos
237 3c43ec9b Panagiotis Kanavos
        private void EnsurePithosContainers()
238 3c43ec9b Panagiotis Kanavos
        {
239 3c43ec9b Panagiotis Kanavos
240 cfed7823 Panagiotis Kanavos
            //Create the two default containers if they are missing
241 c53aa229 Panagiotis Kanavos
            var pithosContainers = new List<string>{ FolderConstants.TrashContainer,FolderConstants.PithosContainer};
242 3c43ec9b Panagiotis Kanavos
            foreach (var container in pithosContainers)
243 cfed7823 Panagiotis Kanavos
            {                
244 c636df1f Panagiotis Kanavos
                var info=CloudClient.GetContainerInfo(UserName, container);
245 5ce54458 Panagiotis Kanavos
                if (info == ContainerInfo.Empty)
246 5ce54458 Panagiotis Kanavos
                {
247 c636df1f Panagiotis Kanavos
                    CloudClient.CreateContainer(UserName, container);
248 c636df1f Panagiotis Kanavos
                    info = CloudClient.GetContainerInfo(UserName, container);
249 5ce54458 Panagiotis Kanavos
                }
250 5ce54458 Panagiotis Kanavos
                _blockSize = info.BlockSize;
251 5ce54458 Panagiotis Kanavos
                _blockHash = info.BlockHash;
252 c53aa229 Panagiotis Kanavos
                _accountInfo.BlockSize = _blockSize;
253 c53aa229 Panagiotis Kanavos
                _accountInfo.BlockHash = _blockHash;
254 3c43ec9b Panagiotis Kanavos
            }
255 3c43ec9b Panagiotis Kanavos
        }
256 3c43ec9b Panagiotis Kanavos
257 79736291 Panagiotis Kanavos
        public string AuthenticationUrl { get; set; }
258 79736291 Panagiotis Kanavos
259 c28a075a Panagiotis Kanavos
        private void IndexLocalFiles()
260 b5061ac8 Panagiotis Kanavos
        {
261 6bcdd8e2 Panagiotis Kanavos
            using (ThreadContext.Stacks["Operation"].Push("Indexing local files"))
262 b5061ac8 Panagiotis Kanavos
            {
263 174bbb6e Panagiotis Kanavos
                
264 5120f3cb Panagiotis Kanavos
                try
265 5120f3cb Panagiotis Kanavos
                {
266 174bbb6e Panagiotis Kanavos
                    //StatusNotification.NotifyChange("Indexing Local Files");
267 174bbb6e Panagiotis Kanavos
                    Log.Info("Start local indexing");
268 174bbb6e Panagiotis Kanavos
                    StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,"Indexing Local Files");                    
269 174bbb6e Panagiotis Kanavos
270 77e10b4f Panagiotis Kanavos
                    var cachePath = Path.Combine(RootPath, FolderConstants.CacheFolder);
271 c28a075a Panagiotis Kanavos
                    var directory = new DirectoryInfo(RootPath);
272 5120f3cb Panagiotis Kanavos
                    var files =
273 5120f3cb Panagiotis Kanavos
                        from file in directory.EnumerateFiles("*", SearchOption.AllDirectories)
274 77e10b4f Panagiotis Kanavos
                        where !file.FullName.StartsWith(cachePath, StringComparison.InvariantCultureIgnoreCase) &&
275 5120f3cb Panagiotis Kanavos
                              !file.Extension.Equals("ignore", StringComparison.InvariantCultureIgnoreCase)
276 5120f3cb Panagiotis Kanavos
                        select file;
277 5120f3cb Panagiotis Kanavos
                    StatusKeeper.ProcessExistingFiles(files);
278 5120f3cb Panagiotis Kanavos
279 5120f3cb Panagiotis Kanavos
                }
280 5120f3cb Panagiotis Kanavos
                catch (Exception exc)
281 5120f3cb Panagiotis Kanavos
                {
282 5120f3cb Panagiotis Kanavos
                    Log.Error("[ERROR]", exc);
283 5120f3cb Panagiotis Kanavos
                }
284 5120f3cb Panagiotis Kanavos
                finally
285 5120f3cb Panagiotis Kanavos
                {
286 5120f3cb Panagiotis Kanavos
                    Log.Info("[END]");
287 5120f3cb Panagiotis Kanavos
                }
288 174bbb6e Panagiotis Kanavos
                StatusNotification.SetPithosStatus(PithosStatus.LocalComplete,"Indexing Completed");
289 b5061ac8 Panagiotis Kanavos
            }
290 b5061ac8 Panagiotis Kanavos
        }
291 b5061ac8 Panagiotis Kanavos
292 9c4346c9 Panagiotis Kanavos
        
293 c53aa229 Panagiotis Kanavos
  
294 eeee29e3 Panagiotis Kanavos
295 eeee29e3 Panagiotis Kanavos
296 70f12b36 Panagiotis Kanavos
       /* private void StartWorkflowAgent()
297 29672672 Panagiotis Kanavos
        {
298 65282d58 Panagiotis Kanavos
            WorkflowAgent.StatusNotification = StatusNotification;
299 65282d58 Panagiotis Kanavos
300 65282d58 Panagiotis Kanavos
/*            //On Vista and up we can check for a network connection
301 56b53955 Panagiotis Kanavos
            bool connected=Environment.OSVersion.Version.Major < 6 || NetworkListManager.IsConnectedToInternet;
302 29672672 Panagiotis Kanavos
            //If we are not connected retry later
303 29672672 Panagiotis Kanavos
            if (!connected)
304 29672672 Panagiotis Kanavos
            {
305 9c4346c9 Panagiotis Kanavos
                Task.Factory.StartNewDelayed(10000, StartWorkflowAgent);
306 29672672 Panagiotis Kanavos
                return;
307 70f12b36 Panagiotis Kanavos
            }#1#
308 29672672 Panagiotis Kanavos
309 29672672 Panagiotis Kanavos
            try
310 29672672 Panagiotis Kanavos
            {
311 9c4346c9 Panagiotis Kanavos
                WorkflowAgent.Start();                
312 29672672 Panagiotis Kanavos
            }
313 29672672 Panagiotis Kanavos
            catch (Exception)
314 29672672 Panagiotis Kanavos
            {
315 29672672 Panagiotis Kanavos
                //Faild to authenticate due to network or account error
316 29672672 Panagiotis Kanavos
                //Retry after a while
317 9c4346c9 Panagiotis Kanavos
                Task.Factory.StartNewDelayed(10000, StartWorkflowAgent);
318 29672672 Panagiotis Kanavos
            }
319 70f12b36 Panagiotis Kanavos
        }*/
320 d78cbf09 Panagiotis Kanavos
321 9c4346c9 Panagiotis Kanavos
        internal class LocalFileComparer:EqualityComparer<CloudAction>
322 d78cbf09 Panagiotis Kanavos
        {
323 9c4346c9 Panagiotis Kanavos
            public override bool Equals(CloudAction x, CloudAction y)
324 d78cbf09 Panagiotis Kanavos
            {
325 d78cbf09 Panagiotis Kanavos
                if (x.Action != y.Action)
326 d78cbf09 Panagiotis Kanavos
                    return false;
327 d78cbf09 Panagiotis Kanavos
                if (x.LocalFile != null && y.LocalFile != null && !x.LocalFile.FullName.Equals(y.LocalFile.FullName))
328 d78cbf09 Panagiotis Kanavos
                    return false;
329 0af3141d Panagiotis Kanavos
                if (x.CloudFile != null && y.CloudFile != null )
330 0af3141d Panagiotis Kanavos
                {
331 0af3141d Panagiotis Kanavos
                    if (x.CloudFile.Hash == null & y.CloudFile.Hash != null)
332 0af3141d Panagiotis Kanavos
                        return false;
333 0af3141d Panagiotis Kanavos
                    if (x.CloudFile.Hash != null & y.CloudFile.Hash == null)
334 0af3141d Panagiotis Kanavos
                        return false;
335 0af3141d Panagiotis Kanavos
                    if (x.CloudFile.Hash == null & y.CloudFile.Hash == null)
336 0af3141d Panagiotis Kanavos
                        return (x.CloudFile.Name == y.CloudFile.Name);
337 0af3141d Panagiotis Kanavos
                    if (!x.CloudFile.Hash.Equals(y.CloudFile.Hash))
338 0af3141d Panagiotis Kanavos
                        return false;
339 0af3141d Panagiotis Kanavos
                }
340 d78cbf09 Panagiotis Kanavos
                if (x.CloudFile == null ^ y.CloudFile == null ||
341 d78cbf09 Panagiotis Kanavos
                    x.LocalFile == null ^ y.LocalFile == null)
342 d78cbf09 Panagiotis Kanavos
                    return false;
343 d78cbf09 Panagiotis Kanavos
                return true;
344 d78cbf09 Panagiotis Kanavos
            }
345 d78cbf09 Panagiotis Kanavos
346 9c4346c9 Panagiotis Kanavos
            public override int GetHashCode(CloudAction obj)
347 d78cbf09 Panagiotis Kanavos
            {
348 c636df1f Panagiotis Kanavos
                if (obj == null)
349 c636df1f Panagiotis Kanavos
                    return 0;
350 d78cbf09 Panagiotis Kanavos
                var hash1 = (obj.LocalFile == null) ? int.MaxValue : obj.LocalFile.FullName.GetHashCode();
351 cfed7823 Panagiotis Kanavos
                var hash2 = (obj.CloudFile == null) ? int.MaxValue : (obj.CloudFile.Hash ?? obj.CloudFile.Name??"").GetHashCode();
352 d78cbf09 Panagiotis Kanavos
                var hash3 = obj.Action.GetHashCode();
353 d78cbf09 Panagiotis Kanavos
                return hash1 ^ hash2 & hash3;
354 d78cbf09 Panagiotis Kanavos
            }
355 9c4346c9 Panagiotis Kanavos
        }        
356 d78cbf09 Panagiotis Kanavos
357 174bbb6e Panagiotis Kanavos
358 c53aa229 Panagiotis Kanavos
        private void StartNetworkAgent()
359 d78cbf09 Panagiotis Kanavos
        {
360 9c4346c9 Panagiotis Kanavos
            NetworkAgent.StatusNotification = StatusNotification;
361 174bbb6e Panagiotis Kanavos
362 174bbb6e Panagiotis Kanavos
            //TODO: The Network and Poll agents are not account specific
363 174bbb6e Panagiotis Kanavos
            //They should be moved outside PithosMonitor
364 c53aa229 Panagiotis Kanavos
            NetworkAgent.Start();
365 d78cbf09 Panagiotis Kanavos
366 fec5da06 Panagiotis Kanavos
            PollAgent.AddAccount(_accountInfo);
367 fec5da06 Panagiotis Kanavos
368 aa7ac00e Panagiotis Kanavos
            PollAgent.StatusNotification = StatusNotification;
369 aa7ac00e Panagiotis Kanavos
370 aa7ac00e Panagiotis Kanavos
            PollAgent.PollRemoteFiles();
371 d78cbf09 Panagiotis Kanavos
        }
372 d78cbf09 Panagiotis Kanavos
373 77e10b4f Panagiotis Kanavos
        //Make sure a hidden cache folder exists to store partial downloads
374 c636df1f Panagiotis Kanavos
        private static void CreateHiddenFolder(string rootPath, string folderName)
375 5ce54458 Panagiotis Kanavos
        {
376 5ce54458 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(rootPath))
377 5ce54458 Panagiotis Kanavos
                throw new ArgumentNullException("rootPath");
378 5ce54458 Panagiotis Kanavos
            if (!Path.IsPathRooted(rootPath))
379 5ce54458 Panagiotis Kanavos
                throw new ArgumentException("rootPath");
380 5ce54458 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(folderName))
381 5ce54458 Panagiotis Kanavos
                throw new ArgumentNullException("folderName");
382 5ce54458 Panagiotis Kanavos
            Contract.EndContractBlock();
383 5ce54458 Panagiotis Kanavos
384 5ce54458 Panagiotis Kanavos
            var folder = Path.Combine(rootPath, folderName);
385 5ce54458 Panagiotis Kanavos
            if (!Directory.Exists(folder))
386 5ce54458 Panagiotis Kanavos
            {
387 5ce54458 Panagiotis Kanavos
                var info = Directory.CreateDirectory(folder);
388 5ce54458 Panagiotis Kanavos
                info.Attributes |= FileAttributes.Hidden;
389 5ce54458 Panagiotis Kanavos
390 77e10b4f Panagiotis Kanavos
                Log.InfoFormat("Created cache Folder: {0}", folder);
391 77e10b4f Panagiotis Kanavos
            }
392 77e10b4f Panagiotis Kanavos
            else
393 77e10b4f Panagiotis Kanavos
            {
394 77e10b4f Panagiotis Kanavos
                var info = new DirectoryInfo(folder);
395 77e10b4f Panagiotis Kanavos
                if ((info.Attributes & FileAttributes.Hidden) == 0)
396 77e10b4f Panagiotis Kanavos
                {
397 77e10b4f Panagiotis Kanavos
                    info.Attributes |= FileAttributes.Hidden;
398 77e10b4f Panagiotis Kanavos
                    Log.InfoFormat("Reset cache folder to hidden: {0}", folder);
399 77e10b4f Panagiotis Kanavos
                }                                
400 5ce54458 Panagiotis Kanavos
            }
401 5ce54458 Panagiotis Kanavos
        }
402 5ce54458 Panagiotis Kanavos
403 b5061ac8 Panagiotis Kanavos
       
404 d78cbf09 Panagiotis Kanavos
405 d78cbf09 Panagiotis Kanavos
406 c28a075a Panagiotis Kanavos
        private void StartWatcherAgent()
407 d78cbf09 Panagiotis Kanavos
        {
408 174bbb6e Panagiotis Kanavos
            if (Log.IsDebugEnabled)
409 174bbb6e Panagiotis Kanavos
                Log.DebugFormat("Start Folder Monitoring [{0}]",RootPath);
410 174bbb6e Panagiotis Kanavos
411 c28a075a Panagiotis Kanavos
            AgentLocator<FileAgent>.Register(FileAgent,RootPath);
412 c28a075a Panagiotis Kanavos
413 5ce54458 Panagiotis Kanavos
            FileAgent.StatusKeeper = StatusKeeper;
414 174bbb6e Panagiotis Kanavos
            FileAgent.StatusNotification = StatusNotification;
415 5ce54458 Panagiotis Kanavos
            FileAgent.Workflow = Workflow;
416 77e10b4f Panagiotis Kanavos
            FileAgent.CachePath = Path.Combine(RootPath, FolderConstants.CacheFolder);
417 c28a075a Panagiotis Kanavos
            FileAgent.Start(_accountInfo, RootPath);
418 d78cbf09 Panagiotis Kanavos
        }
419 d78cbf09 Panagiotis Kanavos
420 d78cbf09 Panagiotis Kanavos
        public void Stop()
421 c28a075a Panagiotis Kanavos
        {
422 c28a075a Panagiotis Kanavos
            AgentLocator<FileAgent>.Remove(RootPath);
423 c28a075a Panagiotis Kanavos
424 c53aa229 Panagiotis Kanavos
            if (FileAgent!=null)
425 c53aa229 Panagiotis Kanavos
                FileAgent.Stop();
426 c53aa229 Panagiotis Kanavos
            FileAgent = null;
427 d78cbf09 Panagiotis Kanavos
        }
428 d78cbf09 Panagiotis Kanavos
429 eeee29e3 Panagiotis Kanavos
430 d78cbf09 Panagiotis Kanavos
        ~PithosMonitor()
431 d78cbf09 Panagiotis Kanavos
        {
432 d78cbf09 Panagiotis Kanavos
            Dispose(false);
433 d78cbf09 Panagiotis Kanavos
        }
434 d78cbf09 Panagiotis Kanavos
435 d78cbf09 Panagiotis Kanavos
        public void Dispose()
436 d78cbf09 Panagiotis Kanavos
        {
437 d78cbf09 Panagiotis Kanavos
            Dispose(true);
438 d78cbf09 Panagiotis Kanavos
            GC.SuppressFinalize(this);
439 d78cbf09 Panagiotis Kanavos
        }
440 d78cbf09 Panagiotis Kanavos
441 d78cbf09 Panagiotis Kanavos
        protected virtual void Dispose(bool disposing)
442 d78cbf09 Panagiotis Kanavos
        {
443 d78cbf09 Panagiotis Kanavos
            if (disposing)
444 d78cbf09 Panagiotis Kanavos
            {
445 d78cbf09 Panagiotis Kanavos
                Stop();
446 d78cbf09 Panagiotis Kanavos
            }
447 d78cbf09 Panagiotis Kanavos
        }
448 d78cbf09 Panagiotis Kanavos
449 d78cbf09 Panagiotis Kanavos
450 5120f3cb Panagiotis Kanavos
        public void MoveFileStates(string oldPath, string newPath)
451 5120f3cb Panagiotis Kanavos
        {
452 5120f3cb Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(oldPath))
453 5120f3cb Panagiotis Kanavos
                throw new ArgumentNullException("oldPath");
454 5120f3cb Panagiotis Kanavos
            if (!Path.IsPathRooted(oldPath))
455 5120f3cb Panagiotis Kanavos
                throw new ArgumentException("oldPath must be an absolute path","oldPath");
456 5120f3cb Panagiotis Kanavos
            if (string.IsNullOrWhiteSpace(newPath))
457 5120f3cb Panagiotis Kanavos
                throw new ArgumentNullException("newPath");
458 5120f3cb Panagiotis Kanavos
            if (!Path.IsPathRooted(newPath))
459 5120f3cb Panagiotis Kanavos
                throw new ArgumentException("newPath must be an absolute path","newPath");
460 5120f3cb Panagiotis Kanavos
            Contract.EndContractBlock();
461 5120f3cb Panagiotis Kanavos
462 5120f3cb Panagiotis Kanavos
            StatusKeeper.ChangeRoots(oldPath, newPath);
463 5120f3cb Panagiotis Kanavos
        }
464 d3a13891 Panagiotis Kanavos
465 fec5da06 Panagiotis Kanavos
        public void SetSelectivePaths(Uri[] uris,Uri[] added, Uri[] removed)
466 d3a13891 Panagiotis Kanavos
        {
467 759bd3c4 Panagiotis Kanavos
            //Convert the uris to paths
468 fec5da06 Panagiotis Kanavos
            var selectivePaths = UrisToFilePaths(uris);
469 fec5da06 Panagiotis Kanavos
            
470 fec5da06 Panagiotis Kanavos
            FileAgent.SelectivePaths=selectivePaths;
471 759bd3c4 Panagiotis Kanavos
            PollAgent.SetSyncUris(uris);
472 4147814e Panagiotis Kanavos
            
473 fec5da06 Panagiotis Kanavos
            var removedPaths = UrisToFilePaths(removed);
474 4147814e Panagiotis Kanavos
            UnversionSelectivePaths(removedPaths);
475 4147814e Panagiotis Kanavos
476 4147814e Panagiotis Kanavos
        }
477 4147814e Panagiotis Kanavos
478 4147814e Panagiotis Kanavos
        /// <summary>
479 4147814e Panagiotis Kanavos
        /// Mark all unselected paths as Unversioned
480 4147814e Panagiotis Kanavos
        /// </summary>
481 4147814e Panagiotis Kanavos
        /// <param name="removed"></param>
482 4147814e Panagiotis Kanavos
        private void UnversionSelectivePaths(List<string> removed)
483 4147814e Panagiotis Kanavos
        {
484 4147814e Panagiotis Kanavos
            if (removed == null)
485 4147814e Panagiotis Kanavos
                return;
486 fec5da06 Panagiotis Kanavos
487 4147814e Panagiotis Kanavos
            //Ensure we remove any file state below the deleted folders
488 4147814e Panagiotis Kanavos
            FileState.UnversionPaths(removed);
489 fec5da06 Panagiotis Kanavos
        }
490 fec5da06 Panagiotis Kanavos
491 4147814e Panagiotis Kanavos
492 fec5da06 Panagiotis Kanavos
        /// <summary>
493 fec5da06 Panagiotis Kanavos
        /// Return a list of absolute filepaths from a list of Uris
494 fec5da06 Panagiotis Kanavos
        /// </summary>
495 fec5da06 Panagiotis Kanavos
        /// <param name="uris"></param>
496 fec5da06 Panagiotis Kanavos
        /// <returns></returns>
497 fec5da06 Panagiotis Kanavos
        private List<string> UrisToFilePaths(IEnumerable<Uri> uris)
498 fec5da06 Panagiotis Kanavos
        {
499 fec5da06 Panagiotis Kanavos
            if (uris == null)
500 fec5da06 Panagiotis Kanavos
                return new List<string>();
501 fec5da06 Panagiotis Kanavos
502 fec5da06 Panagiotis Kanavos
            return (from uri in uris
503 fec5da06 Panagiotis Kanavos
                    let relativePath = _accountInfo.StorageUri
504 fec5da06 Panagiotis Kanavos
                        .MakeRelativeUri(uri)
505 fec5da06 Panagiotis Kanavos
                        .RelativeUriToFilePath()
506 62d5b25f Panagiotis Kanavos
                        //Trim the account name
507 62d5b25f Panagiotis Kanavos
                    select Path.Combine(RootPath, relativePath.After(_accountInfo.UserName + '\\'))).ToList();            
508 d3a13891 Panagiotis Kanavos
        }
509 d3a13891 Panagiotis Kanavos
510 7b0a5fec Panagiotis Kanavos
511 7b0a5fec Panagiotis Kanavos
        public ObjectInfo GetObjectInfo(string filePath)
512 7b0a5fec Panagiotis Kanavos
        {
513 7b0a5fec Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(filePath))
514 7b0a5fec Panagiotis Kanavos
                throw new ArgumentNullException("filePath");
515 7b0a5fec Panagiotis Kanavos
            Contract.EndContractBlock();
516 7b0a5fec Panagiotis Kanavos
517 7b0a5fec Panagiotis Kanavos
            var file=new FileInfo(filePath);
518 7b0a5fec Panagiotis Kanavos
            string relativeUrl;//=file.AsRelativeUrlTo(this.RootPath);
519 7b0a5fec Panagiotis Kanavos
            var relativePath = file.AsRelativeTo(RootPath);
520 7b0a5fec Panagiotis Kanavos
            
521 7b0a5fec Panagiotis Kanavos
            string accountName,container;
522 7b0a5fec Panagiotis Kanavos
            
523 7b0a5fec Panagiotis Kanavos
            var parts=relativePath.Split('\\');
524 7b0a5fec Panagiotis Kanavos
525 7b0a5fec Panagiotis Kanavos
            var accountInfo = _accountInfo;
526 7b0a5fec Panagiotis Kanavos
            if (relativePath.StartsWith(FolderConstants.OthersFolder))
527 7b0a5fec Panagiotis Kanavos
            {                
528 7b0a5fec Panagiotis Kanavos
                accountName = parts[1];
529 7b0a5fec Panagiotis Kanavos
                container = parts[2];
530 7b0a5fec Panagiotis Kanavos
                relativeUrl = String.Join("/", parts.Splice(3));
531 7b0a5fec Panagiotis Kanavos
                //Create the root URL for the target account
532 7b0a5fec Panagiotis Kanavos
                var oldName = UserName;
533 7b0a5fec Panagiotis Kanavos
                var absoluteUri =  _accountInfo.StorageUri.AbsoluteUri;
534 c636df1f Panagiotis Kanavos
                var nameIndex=absoluteUri.IndexOf(oldName, StringComparison.Ordinal);
535 7b0a5fec Panagiotis Kanavos
                var root=absoluteUri.Substring(0, nameIndex);
536 7b0a5fec Panagiotis Kanavos
537 7b0a5fec Panagiotis Kanavos
                accountInfo = new AccountInfo
538 7b0a5fec Panagiotis Kanavos
                {
539 7b0a5fec Panagiotis Kanavos
                    UserName = accountName,
540 7b0a5fec Panagiotis Kanavos
                    AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),
541 7b0a5fec Panagiotis Kanavos
                    StorageUri = new Uri(root + accountName),
542 7b0a5fec Panagiotis Kanavos
                    BlockHash=accountInfo.BlockHash,
543 7b0a5fec Panagiotis Kanavos
                    BlockSize=accountInfo.BlockSize,
544 7b0a5fec Panagiotis Kanavos
                    Token=accountInfo.Token
545 7b0a5fec Panagiotis Kanavos
                };
546 7b0a5fec Panagiotis Kanavos
            }
547 7b0a5fec Panagiotis Kanavos
            else
548 7b0a5fec Panagiotis Kanavos
            {
549 c636df1f Panagiotis Kanavos
                accountName = UserName;
550 7b0a5fec Panagiotis Kanavos
                container = parts[0];
551 7b0a5fec Panagiotis Kanavos
                relativeUrl = String.Join("/", parts.Splice(1));
552 7b0a5fec Panagiotis Kanavos
            }
553 42800be8 Panagiotis Kanavos
            
554 7b0a5fec Panagiotis Kanavos
            var client = new CloudFilesClient(accountInfo);
555 7b0a5fec Panagiotis Kanavos
            var objectInfo=client.GetObjectInfo(accountName, container, relativeUrl);
556 7b0a5fec Panagiotis Kanavos
            return objectInfo;
557 7b0a5fec Panagiotis Kanavos
        }
558 42800be8 Panagiotis Kanavos
        
559 c92e02f3 Panagiotis Kanavos
        public Task<ContainerInfo> GetContainerInfo(string filePath)
560 42800be8 Panagiotis Kanavos
        {
561 42800be8 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(filePath))
562 42800be8 Panagiotis Kanavos
                throw new ArgumentNullException("filePath");
563 42800be8 Panagiotis Kanavos
            Contract.EndContractBlock();
564 42800be8 Panagiotis Kanavos
565 42800be8 Panagiotis Kanavos
            var file=new FileInfo(filePath);
566 42800be8 Panagiotis Kanavos
            var relativePath = file.AsRelativeTo(RootPath);
567 42800be8 Panagiotis Kanavos
            
568 42800be8 Panagiotis Kanavos
            string accountName,container;
569 42800be8 Panagiotis Kanavos
            
570 42800be8 Panagiotis Kanavos
            var parts=relativePath.Split('\\');
571 42800be8 Panagiotis Kanavos
572 42800be8 Panagiotis Kanavos
            var accountInfo = _accountInfo;
573 42800be8 Panagiotis Kanavos
            if (relativePath.StartsWith(FolderConstants.OthersFolder))
574 42800be8 Panagiotis Kanavos
            {                
575 42800be8 Panagiotis Kanavos
                accountName = parts[1];
576 42800be8 Panagiotis Kanavos
                container = parts[2];                
577 42800be8 Panagiotis Kanavos
                //Create the root URL for the target account
578 42800be8 Panagiotis Kanavos
                var oldName = UserName;
579 42800be8 Panagiotis Kanavos
                var absoluteUri =  _accountInfo.StorageUri.AbsoluteUri;
580 c636df1f Panagiotis Kanavos
                var nameIndex=absoluteUri.IndexOf(oldName, StringComparison.Ordinal);
581 42800be8 Panagiotis Kanavos
                var root=absoluteUri.Substring(0, nameIndex);
582 42800be8 Panagiotis Kanavos
583 42800be8 Panagiotis Kanavos
                accountInfo = new AccountInfo
584 42800be8 Panagiotis Kanavos
                {
585 42800be8 Panagiotis Kanavos
                    UserName = accountName,
586 42800be8 Panagiotis Kanavos
                    AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),
587 42800be8 Panagiotis Kanavos
                    StorageUri = new Uri(root + accountName),
588 42800be8 Panagiotis Kanavos
                    BlockHash=accountInfo.BlockHash,
589 42800be8 Panagiotis Kanavos
                    BlockSize=accountInfo.BlockSize,
590 42800be8 Panagiotis Kanavos
                    Token=accountInfo.Token
591 42800be8 Panagiotis Kanavos
                };
592 42800be8 Panagiotis Kanavos
            }
593 42800be8 Panagiotis Kanavos
            else
594 42800be8 Panagiotis Kanavos
            {
595 42800be8 Panagiotis Kanavos
                accountName = UserName;
596 42800be8 Panagiotis Kanavos
                container = parts[0];                
597 42800be8 Panagiotis Kanavos
            }
598 c92e02f3 Panagiotis Kanavos
599 c92e02f3 Panagiotis Kanavos
            return Task.Factory.StartNew(() =>
600 c92e02f3 Panagiotis Kanavos
            {
601 c92e02f3 Panagiotis Kanavos
                var client = new CloudFilesClient(accountInfo);
602 c92e02f3 Panagiotis Kanavos
                var containerInfo = client.GetContainerInfo(accountName, container);
603 c92e02f3 Panagiotis Kanavos
                return containerInfo;
604 c92e02f3 Panagiotis Kanavos
            });
605 42800be8 Panagiotis Kanavos
        }
606 d78cbf09 Panagiotis Kanavos
    }
607 d78cbf09 Panagiotis Kanavos
}