Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / Agents / NetworkAgent.cs @ 537c5f20

History | View | Annotate | Download (24.7 kB)

1 255f5f86 Panagiotis Kanavos
#region
2 255f5f86 Panagiotis Kanavos
/* -----------------------------------------------------------------------
3 255f5f86 Panagiotis Kanavos
 * <copyright file="NetworkAgent.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 f3d080df Panagiotis Kanavos
43 f3d080df Panagiotis Kanavos
using System;
44 9c4346c9 Panagiotis Kanavos
using System.Collections.Generic;
45 9c4346c9 Panagiotis Kanavos
using System.ComponentModel.Composition;
46 9c4346c9 Panagiotis Kanavos
using System.Diagnostics;
47 9c4346c9 Panagiotis Kanavos
using System.Diagnostics.Contracts;
48 9c4346c9 Panagiotis Kanavos
using System.IO;
49 2341c603 pkanavos
using System.Linq;
50 0af3141d Panagiotis Kanavos
using System.Net;
51 db8a9589 Panagiotis Kanavos
using System.Reflection;
52 0b346191 Panagiotis Kanavos
using System.Threading;
53 9c4346c9 Panagiotis Kanavos
using System.Threading.Tasks;
54 e81dd1f6 Panagiotis Kanavos
using Castle.ActiveRecord;
55 9c4346c9 Panagiotis Kanavos
using Pithos.Interfaces;
56 5ce54458 Panagiotis Kanavos
using Pithos.Network;
57 cfed7823 Panagiotis Kanavos
using log4net;
58 9c4346c9 Panagiotis Kanavos
59 9c4346c9 Panagiotis Kanavos
namespace Pithos.Core.Agents
60 9c4346c9 Panagiotis Kanavos
{
61 9c4346c9 Panagiotis Kanavos
    [Export]
62 9c4346c9 Panagiotis Kanavos
    public class NetworkAgent
63 9c4346c9 Panagiotis Kanavos
    {
64 db8a9589 Panagiotis Kanavos
        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
65 db8a9589 Panagiotis Kanavos
66 9036d725 pkanavos
        //private Agent<CloudAction> _agent;
67 9c4346c9 Panagiotis Kanavos
68 3742088d Panagiotis Kanavos
        [System.ComponentModel.Composition.Import]
69 c945b450 pkanavos
        public DeleteAgent DeleteAgent { get; set; }
70 0b346191 Panagiotis Kanavos
71 e81dd1f6 Panagiotis Kanavos
        [System.ComponentModel.Composition.Import]
72 9c4346c9 Panagiotis Kanavos
        public IStatusKeeper StatusKeeper { get; set; }
73 70e0b702 Panagiotis Kanavos
74 70e0b702 Panagiotis Kanavos
        private IStatusNotification _statusNotification;
75 70e0b702 Panagiotis Kanavos
        public IStatusNotification StatusNotification
76 70e0b702 Panagiotis Kanavos
        {
77 70e0b702 Panagiotis Kanavos
            get { return _statusNotification; }
78 70e0b702 Panagiotis Kanavos
            set
79 70e0b702 Panagiotis Kanavos
            {
80 70e0b702 Panagiotis Kanavos
                _statusNotification = value;
81 d78d765c pkanavos
                DeleteAgent.StatusNotification = value;
82 d78d765c pkanavos
                Uploader.StatusNotification = value;
83 d78d765c pkanavos
                Downloader.StatusNotification = value;
84 70e0b702 Panagiotis Kanavos
            }
85 70e0b702 Panagiotis Kanavos
        }
86 9c4346c9 Panagiotis Kanavos
87 cfed7823 Panagiotis Kanavos
88 133f83c2 Panagiotis Kanavos
        [System.ComponentModel.Composition.Import]
89 133f83c2 Panagiotis Kanavos
        public IPithosSettings Settings { get; set; }
90 540b8cf8 Panagiotis Kanavos
91 2341c603 pkanavos
        private Uploader _uploader;
92 2341c603 pkanavos
93 d78d765c pkanavos
        [System.ComponentModel.Composition.Import]
94 2341c603 pkanavos
        public Uploader Uploader
95 2341c603 pkanavos
        {
96 2341c603 pkanavos
            get { return _uploader; }
97 2341c603 pkanavos
            set
98 2341c603 pkanavos
            {
99 2341c603 pkanavos
                _uploader = value;
100 2341c603 pkanavos
                _uploader.UnpauseEvent = _unPauseEvent;                
101 2341c603 pkanavos
            }
102 2341c603 pkanavos
        }
103 2341c603 pkanavos
104 2341c603 pkanavos
        private Downloader _downloader;
105 d78d765c pkanavos
106 d78d765c pkanavos
        [System.ComponentModel.Composition.Import]
107 2341c603 pkanavos
        public Downloader Downloader
108 2341c603 pkanavos
        {
109 2341c603 pkanavos
            get { return _downloader; }
110 2341c603 pkanavos
            set
111 2341c603 pkanavos
            {
112 2341c603 pkanavos
                _downloader = value;
113 2341c603 pkanavos
                _downloader.UnpauseEvent = _unPauseEvent;
114 2341c603 pkanavos
            }
115 2341c603 pkanavos
        }
116 d78d765c pkanavos
117 2341c603 pkanavos
        [System.ComponentModel.Composition.Import]
118 2341c603 pkanavos
        public Selectives Selectives { get; set; }
119 2341c603 pkanavos
        
120 38ac43a6 Panagiotis Kanavos
        //The Proceed signals the poll agent that it can proceed with polling. 
121 38ac43a6 Panagiotis Kanavos
        //Essentially it stops the poll agent to give priority to the network agent
122 aa7ac00e Panagiotis Kanavos
        //Initially the event is signalled because we don't need to pause
123 38ac43a6 Panagiotis Kanavos
        private readonly AsyncManualResetEvent _proceedEvent = new AsyncManualResetEvent(true);
124 2341c603 pkanavos
        private bool _pause;
125 aa7ac00e Panagiotis Kanavos
126 38ac43a6 Panagiotis Kanavos
        public AsyncManualResetEvent ProceedEvent
127 aa7ac00e Panagiotis Kanavos
        {
128 38ac43a6 Panagiotis Kanavos
            get { return _proceedEvent; }
129 aa7ac00e Panagiotis Kanavos
        }
130 303596f9 Panagiotis Kanavos
131 2341c603 pkanavos
        private readonly AsyncManualResetEvent _unPauseEvent = new AsyncManualResetEvent(true);
132 2341c603 pkanavos
133 2341c603 pkanavos
        private CancellationTokenSource _currentOperationCancellation=new CancellationTokenSource();
134 2341c603 pkanavos
135 2341c603 pkanavos
        public void CancelCurrentOperation()
136 2341c603 pkanavos
        {
137 2341c603 pkanavos
            //What does it mean to cancel the current upload/download?
138 2341c603 pkanavos
            //Obviously, the current operation will be cancelled by throwing
139 2341c603 pkanavos
            //a cancellation exception.
140 2341c603 pkanavos
            //
141 2341c603 pkanavos
            //The default behavior is to retry any operations that throw.
142 2341c603 pkanavos
            //Obviously this is not what we want in this situation.
143 2341c603 pkanavos
            //The cancelled operation should NOT bea retried. 
144 2341c603 pkanavos
            //
145 2341c603 pkanavos
            //This can be done by catching the cancellation exception
146 2341c603 pkanavos
            //and avoiding the retry.
147 2341c603 pkanavos
            //
148 2341c603 pkanavos
149 2341c603 pkanavos
            //Have to reset the cancellation source - it is not possible to reset the source
150 2341c603 pkanavos
            //Have to prevent a case where an operation requests a token from the old source
151 2341c603 pkanavos
            var oldSource = Interlocked.Exchange(ref _currentOperationCancellation, new CancellationTokenSource());
152 2341c603 pkanavos
            oldSource.Cancel();
153 2341c603 pkanavos
            
154 2341c603 pkanavos
        }
155 29a6b387 Panagiotis Kanavos
156 9036d725 pkanavos
        /*public void Start()
157 9c4346c9 Panagiotis Kanavos
        {
158 174bbb6e Panagiotis Kanavos
            if (_agent != null)
159 174bbb6e Panagiotis Kanavos
                return;
160 174bbb6e Panagiotis Kanavos
161 174bbb6e Panagiotis Kanavos
            if (Log.IsDebugEnabled)
162 174bbb6e Panagiotis Kanavos
                Log.Debug("Starting Network Agent");
163 174bbb6e Panagiotis Kanavos
164 9c4346c9 Panagiotis Kanavos
            _agent = Agent<CloudAction>.Start(inbox =>
165 9c4346c9 Panagiotis Kanavos
            {
166 9c4346c9 Panagiotis Kanavos
                Action loop = null;
167 9c4346c9 Panagiotis Kanavos
                loop = () =>
168 9c4346c9 Panagiotis Kanavos
                {
169 d78d765c pkanavos
                    DeleteAgent.ProceedEvent.Wait();
170 2341c603 pkanavos
                    _unPauseEvent.Wait();
171 9c4346c9 Panagiotis Kanavos
                    var message = inbox.Receive();
172 a64c87c8 Panagiotis Kanavos
                    var process=message.Then(Process,inbox.CancellationToken);
173 a27aa447 Panagiotis Kanavos
                    inbox.LoopAsync(process, loop);
174 a64c87c8 Panagiotis Kanavos
                };
175 a64c87c8 Panagiotis Kanavos
                loop();
176 f3d080df Panagiotis Kanavos
            });
177 f3d080df Panagiotis Kanavos
178 9036d725 pkanavos
        }*/
179 a27aa447 Panagiotis Kanavos
180 9036d725 pkanavos
/*
181 27361404 Panagiotis Kanavos
        private async Task Process(CloudAction action)
182 a64c87c8 Panagiotis Kanavos
        {
183 a64c87c8 Panagiotis Kanavos
            if (action == null)
184 a64c87c8 Panagiotis Kanavos
                throw new ArgumentNullException("action");
185 c53aa229 Panagiotis Kanavos
            if (action.AccountInfo==null)
186 c53aa229 Panagiotis Kanavos
                throw new ArgumentException("The action.AccountInfo is empty","action");
187 a64c87c8 Panagiotis Kanavos
            Contract.EndContractBlock();
188 a27aa447 Panagiotis Kanavos
189 aa7ac00e Panagiotis Kanavos
190 aa7ac00e Panagiotis Kanavos
191 c53aa229 Panagiotis Kanavos
192 d78d765c pkanavos
            using (ThreadContext.Stacks["Operation"].Push(action.ToString()))
193 cfed7823 Panagiotis Kanavos
            {                
194 cfed7823 Panagiotis Kanavos
195 1bfc38f1 Panagiotis Kanavos
                var cloudFile = action.CloudFile;
196 1bfc38f1 Panagiotis Kanavos
                var downloadPath = action.GetDownloadPath();
197 cfed7823 Panagiotis Kanavos
198 cfed7823 Panagiotis Kanavos
                try
199 aa7ac00e Panagiotis Kanavos
                {
200 174bbb6e Panagiotis Kanavos
                    StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,"Processing");
201 38ac43a6 Panagiotis Kanavos
                    _proceedEvent.Reset();
202 d78d765c pkanavos
                    
203 aa7ac00e Panagiotis Kanavos
                    var accountInfo = action.AccountInfo;
204 aa7ac00e Panagiotis Kanavos
205 14ecd267 Panagiotis Kanavos
                    if (action.Action == CloudActionType.DeleteCloud)
206 eae84ae8 Panagiotis Kanavos
                    {                        
207 14ecd267 Panagiotis Kanavos
                        //Redirect deletes to the delete agent 
208 d78d765c pkanavos
                        DeleteAgent.Post((CloudDeleteAction)action);
209 14ecd267 Panagiotis Kanavos
                    }
210 d78d765c pkanavos
                    if (DeleteAgent.IsDeletedFile(action))
211 14ecd267 Panagiotis Kanavos
                    {
212 14ecd267 Panagiotis Kanavos
                        //Clear the status of already deleted files to avoid reprocessing
213 3c76f045 Panagiotis Kanavos
                        if (action.LocalFile != null)
214 ec1a1baf Panagiotis Kanavos
                            StatusKeeper.ClearFileStatus(action.LocalFile.FullName);
215 14ecd267 Panagiotis Kanavos
                    }
216 14ecd267 Panagiotis Kanavos
                    else
217 14ecd267 Panagiotis Kanavos
                    {
218 14ecd267 Panagiotis Kanavos
                        switch (action.Action)
219 14ecd267 Panagiotis Kanavos
                        {
220 14ecd267 Panagiotis Kanavos
                            case CloudActionType.UploadUnconditional:
221 14ecd267 Panagiotis Kanavos
                                //Abort if the file was deleted before we reached this point
222 fbe71a05 pkanavos
                                var uploadAction = (CloudUploadAction) action;
223 fbe71a05 pkanavos
                                ProcessChildUploads(uploadAction);
224 fbe71a05 pkanavos
                                await Uploader.UploadCloudFile(uploadAction ,CurrentOperationCancelToken);
225 14ecd267 Panagiotis Kanavos
                                break;
226 14ecd267 Panagiotis Kanavos
                            case CloudActionType.DownloadUnconditional:
227 2341c603 pkanavos
                                await Downloader.DownloadCloudFile(accountInfo, cloudFile, downloadPath, CurrentOperationCancelToken);
228 14ecd267 Panagiotis Kanavos
                                break;
229 14ecd267 Panagiotis Kanavos
                            case CloudActionType.RenameCloud:
230 e5b65606 Panagiotis Kanavos
                                var moveAction = (CloudMoveAction)action;
231 039a89e5 Panagiotis Kanavos
                                RenameCloudFile(accountInfo, moveAction);
232 14ecd267 Panagiotis Kanavos
                                break;
233 b666b39a Panagiotis Kanavos
                            case CloudActionType.RenameLocal:
234 b666b39a Panagiotis Kanavos
                                RenameLocalFile(accountInfo, action);
235 b666b39a Panagiotis Kanavos
                                break;
236 14ecd267 Panagiotis Kanavos
                            case CloudActionType.MustSynch:
237 14ecd267 Panagiotis Kanavos
                                if (!File.Exists(downloadPath) && !Directory.Exists(downloadPath))
238 14ecd267 Panagiotis Kanavos
                                {
239 2341c603 pkanavos
                                    await Downloader.DownloadCloudFile(accountInfo, cloudFile, downloadPath, CurrentOperationCancelToken);
240 14ecd267 Panagiotis Kanavos
                                }
241 14ecd267 Panagiotis Kanavos
                                else
242 14ecd267 Panagiotis Kanavos
                                {
243 039a89e5 Panagiotis Kanavos
                                    await SyncFiles(accountInfo, action);
244 14ecd267 Panagiotis Kanavos
                                }
245 14ecd267 Panagiotis Kanavos
                                break;
246 14ecd267 Panagiotis Kanavos
                        }
247 cfed7823 Panagiotis Kanavos
                    }
248 6bcdd8e2 Panagiotis Kanavos
                    Log.InfoFormat("End Processing {0}:{1}->{2}", action.Action, action.LocalFile,
249 cfed7823 Panagiotis Kanavos
                                           action.CloudFile.Name);
250 cfed7823 Panagiotis Kanavos
                }
251 d78d765c pkanavos
/*
252 a0dcfcc9 Panagiotis Kanavos
                catch (WebException exc)
253 d78d765c pkanavos
                {                    
254 73cdd135 Panagiotis Kanavos
                    Log.ErrorFormat("[WEB ERROR] {0} : {1} -> {2} due to exception\r\n{3}", action.Action, action.LocalFile, action.CloudFile, exc);
255 d78d765c pkanavos
                    
256 d78d765c pkanavos
                    
257 d78d765c pkanavos
                    //Actions that resulted in server errors should be retried                    
258 d78d765c pkanavos
                    var response = exc.Response as HttpWebResponse;
259 d78d765c pkanavos
                    if (response != null && response.StatusCode >= HttpStatusCode.InternalServerError)
260 d78d765c pkanavos
                    {
261 d78d765c pkanavos
                        _agent.Post(action);
262 d78d765c pkanavos
                        Log.WarnFormat("[REQUEUE] {0} : {1} -> {2}", action.Action, action.LocalFile, action.CloudFile);
263 d78d765c pkanavos
                    }
264 a0dcfcc9 Panagiotis Kanavos
                }
265 9036d725 pkanavos
#1#
266 2341c603 pkanavos
                catch (OperationCanceledException ex)
267 2341c603 pkanavos
                {                    
268 2341c603 pkanavos
                    Log.WarnFormat("Cancelling [{0}]",ex);
269 cfed7823 Panagiotis Kanavos
                }
270 73cdd135 Panagiotis Kanavos
                catch (DirectoryNotFoundException)
271 73cdd135 Panagiotis Kanavos
                {
272 73cdd135 Panagiotis Kanavos
                    Log.ErrorFormat("{0} : {1} -> {2}  failed because the directory was not found.\n Rescheduling a delete",
273 73cdd135 Panagiotis Kanavos
                        action.Action, action.LocalFile, action.CloudFile);
274 73cdd135 Panagiotis Kanavos
                    //Post a delete action for the missing file
275 e5b65606 Panagiotis Kanavos
                    Post(new CloudDeleteAction(action));
276 73cdd135 Panagiotis Kanavos
                }
277 73cdd135 Panagiotis Kanavos
                catch (FileNotFoundException)
278 cfed7823 Panagiotis Kanavos
                {
279 cfed7823 Panagiotis Kanavos
                    Log.ErrorFormat("{0} : {1} -> {2}  failed because the file was not found.\n Rescheduling a delete",
280 73cdd135 Panagiotis Kanavos
                        action.Action, action.LocalFile, action.CloudFile);
281 1bfc38f1 Panagiotis Kanavos
                    //Post a delete action for the missing file
282 1bfc38f1 Panagiotis Kanavos
                    Post(new CloudDeleteAction(action));
283 cfed7823 Panagiotis Kanavos
                }
284 cfed7823 Panagiotis Kanavos
                catch (Exception exc)
285 cfed7823 Panagiotis Kanavos
                {
286 cfed7823 Panagiotis Kanavos
                    Log.ErrorFormat("[REQUEUE] {0} : {1} -> {2} due to exception\r\n{3}",
287 cfed7823 Panagiotis Kanavos
                                     action.Action, action.LocalFile, action.CloudFile, exc);
288 cfed7823 Panagiotis Kanavos
289 cfed7823 Panagiotis Kanavos
                    _agent.Post(action);
290 e5b65606 Panagiotis Kanavos
                }
291 e5b65606 Panagiotis Kanavos
                finally
292 e5b65606 Panagiotis Kanavos
                {
293 aa7ac00e Panagiotis Kanavos
                    if (_agent.IsEmpty)
294 38ac43a6 Panagiotis Kanavos
                        _proceedEvent.Set();
295 174bbb6e Panagiotis Kanavos
                    UpdateStatus(PithosStatus.LocalComplete);                                        
296 e5b65606 Panagiotis Kanavos
                }
297 cfed7823 Panagiotis Kanavos
            }
298 cfed7823 Panagiotis Kanavos
        }
299 9036d725 pkanavos
*/
300 cfed7823 Panagiotis Kanavos
301 9036d725 pkanavos
    /*    private void ProcessChildUploads(CloudUploadAction uploadAction)
302 fbe71a05 pkanavos
        {
303 fbe71a05 pkanavos
            if (!uploadAction.IsCreation || !(uploadAction.LocalFile is DirectoryInfo)) 
304 fbe71a05 pkanavos
                return;
305 fbe71a05 pkanavos
306 fbe71a05 pkanavos
            var dirInfo = uploadAction.LocalFile as DirectoryInfo;
307 fbe71a05 pkanavos
308 fbe71a05 pkanavos
            var account = uploadAction.AccountInfo;
309 50bf81e8 pkanavos
            var folderActions = from info in dirInfo.EnumerateDirectories("*", SearchOption.AllDirectories)                          
310 fbe71a05 pkanavos
                          select
311 50bf81e8 pkanavos
                              new CloudUploadAction(account, info, null, account.BlockSize, account.BlockHash,
312 fbe71a05 pkanavos
                                                    uploadAction, true);
313 50bf81e8 pkanavos
            var fileActions = from info in dirInfo.EnumerateFiles("*", SearchOption.AllDirectories)                          
314 50bf81e8 pkanavos
                          select
315 50bf81e8 pkanavos
                              new CloudUploadAction(account, info, null, account.BlockSize, account.BlockHash,
316 50bf81e8 pkanavos
                                                    uploadAction, true);            
317 50bf81e8 pkanavos
            //Post folder actions first, to ensure the selective folders are updated
318 50bf81e8 pkanavos
            folderActions.ApplyAction(PostUploadAction);
319 50bf81e8 pkanavos
            fileActions.ApplyAction(PostUploadAction);            
320 50bf81e8 pkanavos
        }
321 9036d725 pkanavos
*/
322 9036d725 pkanavos
/*
323 50bf81e8 pkanavos
        private void PostUploadAction(CloudUploadAction action)
324 50bf81e8 pkanavos
        {
325 50bf81e8 pkanavos
            var state = StatusKeeper.GetStateByFilePath(action.LocalFile.FullName);
326 50bf81e8 pkanavos
            if (state != null)
327 50bf81e8 pkanavos
                state.Delete();
328 50bf81e8 pkanavos
            //StatusKeeper.SetFileState(action.LocalFile.FullName,FileStatus.Created,FileOverlayStatus.Normal,String.Empty);
329 50bf81e8 pkanavos
            state = FileState.CreateFor(action.LocalFile);
330 50bf81e8 pkanavos
            //StatusKeeper.SetFileStatus();
331 50bf81e8 pkanavos
            state.FileStatus = FileStatus.Created;
332 50bf81e8 pkanavos
            state.OverlayStatus = FileOverlayStatus.Normal;
333 50bf81e8 pkanavos
            state.Create();
334 50bf81e8 pkanavos
            action.FileState = state;
335 50bf81e8 pkanavos
            Post(action);
336 fbe71a05 pkanavos
        }
337 9036d725 pkanavos
*/
338 fbe71a05 pkanavos
339 9036d725 pkanavos
        public CancellationToken CurrentOperationCancelToken
340 2341c603 pkanavos
        {
341 2341c603 pkanavos
            get { return _currentOperationCancellation.Token; }
342 2341c603 pkanavos
        }
343 2341c603 pkanavos
344 b666b39a Panagiotis Kanavos
345 eae84ae8 Panagiotis Kanavos
        private void UpdateStatus(PithosStatus status)
346 eae84ae8 Panagiotis Kanavos
        {
347 174bbb6e Panagiotis Kanavos
            StatusNotification.SetPithosStatus(status);
348 174bbb6e Panagiotis Kanavos
            //StatusNotification.Notify(new Notification());
349 eae84ae8 Panagiotis Kanavos
        }
350 eae84ae8 Panagiotis Kanavos
351 b666b39a Panagiotis Kanavos
        private void RenameLocalFile(AccountInfo accountInfo, CloudAction action)
352 b666b39a Panagiotis Kanavos
        {
353 b666b39a Panagiotis Kanavos
            if (accountInfo == null)
354 b666b39a Panagiotis Kanavos
                throw new ArgumentNullException("accountInfo");
355 b666b39a Panagiotis Kanavos
            if (action == null)
356 b666b39a Panagiotis Kanavos
                throw new ArgumentNullException("action");
357 b666b39a Panagiotis Kanavos
            if (action.LocalFile == null)
358 b666b39a Panagiotis Kanavos
                throw new ArgumentException("The action's local file is not specified", "action");
359 b666b39a Panagiotis Kanavos
            if (!Path.IsPathRooted(action.LocalFile.FullName))
360 b666b39a Panagiotis Kanavos
                throw new ArgumentException("The action's local file path must be absolute", "action");
361 b666b39a Panagiotis Kanavos
            if (action.CloudFile == null)
362 b666b39a Panagiotis Kanavos
                throw new ArgumentException("The action's cloud file is not specified", "action");
363 b666b39a Panagiotis Kanavos
            Contract.EndContractBlock();
364 6bcdd8e2 Panagiotis Kanavos
            using (ThreadContext.Stacks["Operation"].Push("RenameLocalFile"))
365 6bcdd8e2 Panagiotis Kanavos
            {
366 b666b39a Panagiotis Kanavos
367 6bcdd8e2 Panagiotis Kanavos
                //We assume that the local file already exists, otherwise the poll agent
368 6bcdd8e2 Panagiotis Kanavos
                //would have issued a download request
369 b666b39a Panagiotis Kanavos
370 6bcdd8e2 Panagiotis Kanavos
                var currentInfo = action.CloudFile;
371 6bcdd8e2 Panagiotis Kanavos
                var previousInfo = action.CloudFile.Previous;
372 6bcdd8e2 Panagiotis Kanavos
                var fileAgent = FileAgent.GetFileAgent(accountInfo);
373 b666b39a Panagiotis Kanavos
374 6bcdd8e2 Panagiotis Kanavos
                var previousRelativepath = previousInfo.RelativeUrlToFilePath(accountInfo.UserName);
375 6bcdd8e2 Panagiotis Kanavos
                var previousFile = fileAgent.GetFileSystemInfo(previousRelativepath);
376 b666b39a Panagiotis Kanavos
377 6bcdd8e2 Panagiotis Kanavos
                //In every case we need to move the local file first
378 6bcdd8e2 Panagiotis Kanavos
                MoveLocalFile(accountInfo, previousFile, fileAgent, currentInfo);
379 6bcdd8e2 Panagiotis Kanavos
            }
380 b666b39a Panagiotis Kanavos
        }
381 b666b39a Panagiotis Kanavos
382 b666b39a Panagiotis Kanavos
        private void MoveLocalFile(AccountInfo accountInfo, FileSystemInfo previousFile, FileAgent fileAgent,
383 b666b39a Panagiotis Kanavos
                                   ObjectInfo currentInfo)
384 b666b39a Panagiotis Kanavos
        {
385 b666b39a Panagiotis Kanavos
            var currentRelativepath = currentInfo.RelativeUrlToFilePath(accountInfo.UserName);
386 b666b39a Panagiotis Kanavos
            var newPath = Path.Combine(fileAgent.RootPath, currentRelativepath);
387 b666b39a Panagiotis Kanavos
388 b666b39a Panagiotis Kanavos
            var isFile= (previousFile is FileInfo);
389 b666b39a Panagiotis Kanavos
            var previousFullPath = isFile? 
390 b666b39a Panagiotis Kanavos
                FileInfoExtensions.GetProperFilePathCapitalization(previousFile.FullName):
391 b666b39a Panagiotis Kanavos
                FileInfoExtensions.GetProperDirectoryCapitalization(previousFile.FullName);                
392 b666b39a Panagiotis Kanavos
            
393 d78d765c pkanavos
            using (NetworkGate.Acquire(previousFullPath, NetworkOperation.Renaming))
394 d78d765c pkanavos
            using (NetworkGate.Acquire(newPath,NetworkOperation.Renaming)) 
395 b666b39a Panagiotis Kanavos
            using (new SessionScope(FlushAction.Auto))
396 b666b39a Panagiotis Kanavos
            {
397 b666b39a Panagiotis Kanavos
                if (isFile)
398 b666b39a Panagiotis Kanavos
                    (previousFile as FileInfo).MoveTo(newPath);
399 b666b39a Panagiotis Kanavos
                else
400 b666b39a Panagiotis Kanavos
                {
401 b666b39a Panagiotis Kanavos
                    (previousFile as DirectoryInfo).MoveTo(newPath);
402 b666b39a Panagiotis Kanavos
                }
403 b666b39a Panagiotis Kanavos
                var state = StatusKeeper.GetStateByFilePath(previousFullPath);
404 b666b39a Panagiotis Kanavos
                state.FilePath = newPath;
405 b666b39a Panagiotis Kanavos
                state.SaveCopy();
406 0a9d4d18 pkanavos
                StatusKeeper.SetFileState(previousFullPath,FileStatus.Deleted,FileOverlayStatus.Deleted, "Deleted");
407 b666b39a Panagiotis Kanavos
            }            
408 b666b39a Panagiotis Kanavos
        }
409 b666b39a Panagiotis Kanavos
410 732276d3 pkanavos
/*        private async Task SyncFiles(AccountInfo accountInfo,CloudAction action)
411 cfed7823 Panagiotis Kanavos
        {
412 c53aa229 Panagiotis Kanavos
            if (accountInfo == null)
413 c53aa229 Panagiotis Kanavos
                throw new ArgumentNullException("accountInfo");
414 cfed7823 Panagiotis Kanavos
            if (action==null)
415 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("action");
416 cfed7823 Panagiotis Kanavos
            if (action.LocalFile==null)
417 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The action's local file is not specified","action");
418 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(action.LocalFile.FullName))
419 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The action's local file path must be absolute","action");
420 cfed7823 Panagiotis Kanavos
            if (action.CloudFile== null)
421 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The action's cloud file is not specified", "action");
422 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
423 6bcdd8e2 Panagiotis Kanavos
            using (ThreadContext.Stacks["Operation"].Push("SyncFiles"))
424 6bcdd8e2 Panagiotis Kanavos
            {
425 cfed7823 Panagiotis Kanavos
426 d78d765c pkanavos
                //var localFile = action.LocalFile;
427 6bcdd8e2 Panagiotis Kanavos
                var cloudFile = action.CloudFile;
428 6bcdd8e2 Panagiotis Kanavos
                var downloadPath = action.LocalFile.GetProperCapitalization();
429 a27aa447 Panagiotis Kanavos
430 1cc1e8c5 pkanavos
                var cloudHash = cloudFile.X_Object_Hash.ToLower();
431 268bec7f pkanavos
                var previousCloudHash = cloudFile.PreviousHash == null?null: cloudFile.PreviousHash.ToLower();
432 174bbb6e Panagiotis Kanavos
                var localHash = action.TreeHash.Value.TopHash.ToHashString();// LocalHash.Value.ToLower();
433 174bbb6e Panagiotis Kanavos
                //var topHash = action.TopHash.Value.ToLower();
434 cfed7823 Panagiotis Kanavos
435 268bec7f pkanavos
                if(cloudFile.IsDirectory && action.LocalFile is DirectoryInfo)
436 268bec7f pkanavos
                {
437 268bec7f pkanavos
                    Log.InfoFormat("Skipping folder {0} , exists in server", downloadPath);
438 268bec7f pkanavos
                    return;
439 268bec7f pkanavos
                }
440 268bec7f pkanavos
441 6bcdd8e2 Panagiotis Kanavos
                //At this point we know that an object has changed on the server and that a local
442 6bcdd8e2 Panagiotis Kanavos
                //file already exists. We need to decide whether the file has only changed on 
443 6bcdd8e2 Panagiotis Kanavos
                //the server or there is a conflicting change on the client.
444 6bcdd8e2 Panagiotis Kanavos
                //
445 cfed7823 Panagiotis Kanavos
446 174bbb6e Panagiotis Kanavos
                //If the hashes match, we are done
447 d78d765c pkanavos
                if (cloudFile != ObjectInfo.Empty && cloudHash == localHash)
448 6bcdd8e2 Panagiotis Kanavos
                {
449 6bcdd8e2 Panagiotis Kanavos
                    Log.InfoFormat("Skipping {0}, hashes match", downloadPath);
450 6bcdd8e2 Panagiotis Kanavos
                    return;
451 6bcdd8e2 Panagiotis Kanavos
                }
452 f6ca240a Panagiotis Kanavos
453 d21f3c77 pkanavos
                //If the local and remote files have 0 length their hashes will not match
454 d21f3c77 pkanavos
                if (!cloudFile.IsDirectory && cloudFile.Bytes==0 && action.LocalFile is FileInfo && (action.LocalFile as FileInfo).Length==0 )
455 d21f3c77 pkanavos
                {
456 d21f3c77 pkanavos
                    Log.InfoFormat("Skipping {0}, files are empty", downloadPath);
457 d21f3c77 pkanavos
                    return;
458 d21f3c77 pkanavos
                }
459 d21f3c77 pkanavos
460 6bcdd8e2 Panagiotis Kanavos
                //The hashes DON'T match. We need to sync
461 6bcdd8e2 Panagiotis Kanavos
462 6bcdd8e2 Panagiotis Kanavos
                // If the previous tophash matches the local tophash, the file was only changed on the server. 
463 6bcdd8e2 Panagiotis Kanavos
                if (localHash == previousCloudHash)
464 6bcdd8e2 Panagiotis Kanavos
                {
465 732276d3 pkanavos
                    await Downloader.DownloadCloudFile(accountInfo, cloudFile, downloadPath CurrentOperationCancelToken);
466 6bcdd8e2 Panagiotis Kanavos
                }
467 6bcdd8e2 Panagiotis Kanavos
                else
468 6bcdd8e2 Panagiotis Kanavos
                {
469 6bcdd8e2 Panagiotis Kanavos
                    //If the previous and local hash don't match, there was a local conflict
470 6bcdd8e2 Panagiotis Kanavos
                    //that was not uploaded to the server. We have a conflict
471 e3bc51ba pkanavos
                    ReportConflictForMismatch(downloadPath);
472 6bcdd8e2 Panagiotis Kanavos
                }
473 cfed7823 Panagiotis Kanavos
            }
474 732276d3 pkanavos
        }*/
475 cfed7823 Panagiotis Kanavos
476 e3bc51ba pkanavos
        private void ReportConflictForMismatch(string downloadPath)
477 cfed7823 Panagiotis Kanavos
        {
478 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(downloadPath))
479 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("downloadPath");
480 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
481 cfed7823 Panagiotis Kanavos
482 368e06fd pkanavos
            StatusKeeper.SetFileState(downloadPath,FileStatus.Conflict, FileOverlayStatus.Conflict,"File changed at the server");
483 eae84ae8 Panagiotis Kanavos
            UpdateStatus(PithosStatus.HasConflicts);
484 cfed7823 Panagiotis Kanavos
            var message = String.Format("Conflict detected for file {0}", downloadPath);
485 cfed7823 Panagiotis Kanavos
            Log.Warn(message);
486 cfed7823 Panagiotis Kanavos
            StatusNotification.NotifyChange(message, TraceLevel.Warning);
487 cfed7823 Panagiotis Kanavos
        }
488 cfed7823 Panagiotis Kanavos
489 9036d725 pkanavos
/*
490 9c4346c9 Panagiotis Kanavos
        public void Post(CloudAction cloudAction)
491 9c4346c9 Panagiotis Kanavos
        {
492 9c4346c9 Panagiotis Kanavos
            if (cloudAction == null)
493 9c4346c9 Panagiotis Kanavos
                throw new ArgumentNullException("cloudAction");
494 c53aa229 Panagiotis Kanavos
            if (cloudAction.AccountInfo==null)
495 c53aa229 Panagiotis Kanavos
                throw new ArgumentException("The CloudAction.AccountInfo is empty","cloudAction");
496 9c4346c9 Panagiotis Kanavos
            Contract.EndContractBlock();
497 f3d080df Panagiotis Kanavos
498 d78d765c pkanavos
            DeleteAgent.ProceedEvent.Wait();
499 f3d080df Panagiotis Kanavos
            
500 f3d080df Panagiotis Kanavos
            if (cloudAction is CloudDeleteAction)
501 d78d765c pkanavos
                DeleteAgent.Post((CloudDeleteAction)cloudAction);
502 f3d080df Panagiotis Kanavos
            else
503 f3d080df Panagiotis Kanavos
                _agent.Post(cloudAction);
504 9c4346c9 Panagiotis Kanavos
        }
505 9036d725 pkanavos
*/
506 a9faac18 Panagiotis Kanavos
       
507 9c4346c9 Panagiotis Kanavos
508 9036d725 pkanavos
/*
509 aa7ac00e Panagiotis Kanavos
        public IEnumerable<CloudAction> GetEnumerable()
510 540b8cf8 Panagiotis Kanavos
        {
511 aa7ac00e Panagiotis Kanavos
            return _agent.GetEnumerable();
512 540b8cf8 Panagiotis Kanavos
        }
513 9036d725 pkanavos
*/
514 540b8cf8 Panagiotis Kanavos
515 aa7ac00e Panagiotis Kanavos
        public Task GetDeleteAwaiter()
516 5750d7cc Panagiotis Kanavos
        {
517 d78d765c pkanavos
            return DeleteAgent.ProceedEvent.WaitAsync();
518 5750d7cc Panagiotis Kanavos
        }
519 9036d725 pkanavos
/*
520 aa7ac00e Panagiotis Kanavos
        public CancellationToken CancellationToken
521 422c9598 Panagiotis Kanavos
        {
522 aa7ac00e Panagiotis Kanavos
            get { return _agent.CancellationToken; }
523 422c9598 Panagiotis Kanavos
        }
524 9036d725 pkanavos
*/
525 422c9598 Panagiotis Kanavos
526 2341c603 pkanavos
        public bool Pause
527 2341c603 pkanavos
        {
528 2341c603 pkanavos
            get {
529 2341c603 pkanavos
                return _pause;
530 2341c603 pkanavos
            }
531 2341c603 pkanavos
            set {
532 2341c603 pkanavos
                _pause = value;
533 2341c603 pkanavos
                if (_pause)
534 2341c603 pkanavos
                    _unPauseEvent.Reset();
535 2341c603 pkanavos
                else
536 2341c603 pkanavos
                {
537 2341c603 pkanavos
                    _unPauseEvent.Set();
538 2341c603 pkanavos
                }
539 2341c603 pkanavos
            }
540 2341c603 pkanavos
        }
541 0af3141d Panagiotis Kanavos
542 9c4346c9 Panagiotis Kanavos
543 27361404 Panagiotis Kanavos
        private void RenameCloudFile(AccountInfo accountInfo,CloudMoveAction action)
544 9c4346c9 Panagiotis Kanavos
        {
545 c53aa229 Panagiotis Kanavos
            if (accountInfo==null)
546 c53aa229 Panagiotis Kanavos
                throw new ArgumentNullException("accountInfo");
547 1bfc38f1 Panagiotis Kanavos
            if (action==null)
548 1bfc38f1 Panagiotis Kanavos
                throw new ArgumentNullException("action");
549 27361404 Panagiotis Kanavos
            if (action.CloudFile==null)
550 27361404 Panagiotis Kanavos
                throw new ArgumentException("CloudFile","action");
551 27361404 Panagiotis Kanavos
            if (action.LocalFile==null)
552 27361404 Panagiotis Kanavos
                throw new ArgumentException("LocalFile","action");
553 27361404 Panagiotis Kanavos
            if (action.OldLocalFile==null)
554 27361404 Panagiotis Kanavos
                throw new ArgumentException("OldLocalFile","action");
555 27361404 Panagiotis Kanavos
            if (action.OldCloudFile==null)
556 27361404 Panagiotis Kanavos
                throw new ArgumentException("OldCloudFile","action");
557 9c4346c9 Panagiotis Kanavos
            Contract.EndContractBlock();
558 f3d080df Panagiotis Kanavos
559 6bcdd8e2 Panagiotis Kanavos
            using (ThreadContext.Stacks["Operation"].Push("RenameCloudFile"))
560 6bcdd8e2 Panagiotis Kanavos
            {
561 9c4346c9 Panagiotis Kanavos
562 6bcdd8e2 Panagiotis Kanavos
                var newFilePath = action.LocalFile.FullName;
563 6bcdd8e2 Panagiotis Kanavos
564 6bcdd8e2 Panagiotis Kanavos
                //How do we handle concurrent renames and deletes/uploads/downloads?
565 6bcdd8e2 Panagiotis Kanavos
                //* A conflicting upload means that a file was renamed before it had a chance to finish uploading
566 6bcdd8e2 Panagiotis Kanavos
                //  This should never happen as the network agent executes only one action at a time
567 6bcdd8e2 Panagiotis Kanavos
                //* A conflicting download means that the file was modified on the cloud. While we can go on and complete
568 6bcdd8e2 Panagiotis Kanavos
                //  the rename, there may be a problem if the file is downloaded in blocks, as subsequent block requests for the 
569 6bcdd8e2 Panagiotis Kanavos
                //  same name will fail.
570 6bcdd8e2 Panagiotis Kanavos
                //  This should never happen as the network agent executes only one action at a time.
571 6bcdd8e2 Panagiotis Kanavos
                //* A conflicting delete can happen if the rename was followed by a delete action that didn't have the chance
572 6bcdd8e2 Panagiotis Kanavos
                //  to remove the rename from the queue.
573 6bcdd8e2 Panagiotis Kanavos
                //  We can probably ignore this case. It will result in an error which should be ignored            
574 1bfc38f1 Panagiotis Kanavos
575 9c4346c9 Panagiotis Kanavos
576 6bcdd8e2 Panagiotis Kanavos
                //The local file is already renamed
577 fbe71a05 pkanavos
                StatusKeeper.SetFileOverlayStatus(newFilePath, FileOverlayStatus.Modified).Wait();
578 6bcdd8e2 Panagiotis Kanavos
579 6bcdd8e2 Panagiotis Kanavos
580 6bcdd8e2 Panagiotis Kanavos
                var account = action.CloudFile.Account ?? accountInfo.UserName;
581 6bcdd8e2 Panagiotis Kanavos
                var container = action.CloudFile.Container;
582 6bcdd8e2 Panagiotis Kanavos
583 6bcdd8e2 Panagiotis Kanavos
                var client = new CloudFilesClient(accountInfo);
584 6bcdd8e2 Panagiotis Kanavos
                //TODO: What code is returned when the source file doesn't exist?
585 6bcdd8e2 Panagiotis Kanavos
                client.MoveObject(account, container, action.OldCloudFile.Name, container, action.CloudFile.Name);
586 6bcdd8e2 Panagiotis Kanavos
587 6bcdd8e2 Panagiotis Kanavos
                StatusKeeper.SetFileStatus(newFilePath, FileStatus.Unchanged);
588 fbe71a05 pkanavos
                StatusKeeper.SetFileOverlayStatus(newFilePath, FileOverlayStatus.Normal).Wait();
589 6bcdd8e2 Panagiotis Kanavos
                NativeMethods.RaiseChangeNotification(newFilePath);
590 6bcdd8e2 Panagiotis Kanavos
            }
591 9c4346c9 Panagiotis Kanavos
        }
592 9c4346c9 Panagiotis Kanavos
593 a27aa447 Panagiotis Kanavos
594 2341c603 pkanavos
        
595 a27aa447 Panagiotis Kanavos
596 9c4346c9 Panagiotis Kanavos
    }
597 9c4346c9 Panagiotis Kanavos
598 5ce54458 Panagiotis Kanavos
   
599 5ce54458 Panagiotis Kanavos
600 9c4346c9 Panagiotis Kanavos
601 9c4346c9 Panagiotis Kanavos
}