Selective Sync fixes
[pithos-ms-client] / trunk / Pithos.Core / Agents / CloudTransferAction.cs
1 #region
2 /* -----------------------------------------------------------------------
3  * <copyright file="CloudTransferAction.cs" company="GRNet">
4  * 
5  * Copyright 2011-2012 GRNET S.A. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or
8  * without modification, are permitted provided that the following
9  * conditions are met:
10  *
11  *   1. Redistributions of source code must retain the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer.
14  *
15  *   2. Redistributions in binary form must reproduce the above
16  *      copyright notice, this list of conditions and the following
17  *      disclaimer in the documentation and/or other materials
18  *      provided with the distribution.
19  *
20  *
21  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * The views and conclusions contained in the software and
35  * documentation are those of the authors and should not be
36  * interpreted as representing official policies, either expressed
37  * or implied, of GRNET S.A.
38  * </copyright>
39  * -----------------------------------------------------------------------
40  */
41 #endregion
42 using System;
43 using System.Diagnostics.Contracts;
44 using System.IO;
45 using System.Threading;
46 using Pithos.Interfaces;
47 using Pithos.Network;
48
49 namespace Pithos.Core.Agents
50 {
51     public enum CloudActionType
52     {
53         MustSynch,
54         UploadUnconditional,
55         DownloadUnconditional,
56         DeleteLocal,
57         DeleteCloud,
58         RenameCloud,
59         RenameLocal
60     }
61
62     public class CloudAction
63     {
64         public AccountInfo AccountInfo { get; set; }
65         public CloudActionType Action { get; set; }
66         public FileSystemInfo LocalFile { get; set; }
67         public ObjectInfo CloudFile { get; set; }
68         public FileState FileState { get; set; }
69         public string Container { get; set; }
70
71         public readonly DateTime Created = DateTime.Now;
72
73
74         public Lazy<TreeHash> TreeHash { get; protected set; }
75         //public Lazy<string> TopHash { get; set; }
76
77
78         [ContractInvariantMethod]
79         private void Invariants()
80         {
81             Contract.Invariant(AccountInfo!=null);
82         }
83
84         public bool IsShared
85         {
86             get { return  CloudFile!=null && AccountInfo.UserName != CloudFile.Account; }
87         }
88
89         protected CloudAction(AccountInfo accountInfo,CloudActionType action)
90         {
91             if (accountInfo==null)
92                 throw new ArgumentNullException("accountInfo");
93             Contract.EndContractBlock();
94
95             Action = action;
96             AccountInfo = accountInfo;
97         }
98
99         public CloudAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo localFile, ObjectInfo cloudFile, FileState state, int blockSize, string algorithm)
100             : this(accountInfo,action)
101         {
102             if(blockSize<=0)
103                 throw new ArgumentOutOfRangeException("blockSize");
104             Contract.EndContractBlock();
105             LocalFile = localFile.WithProperCapitalization();
106             CloudFile = cloudFile;
107             FileState = state;
108             
109             if (LocalFile == null) 
110                 return;
111
112             TreeHash = new Lazy<TreeHash>(() => Signature.CalculateTreeHash(LocalFile, blockSize,algorithm),
113                                             LazyThreadSafetyMode.ExecutionAndPublication);
114         }
115
116         //Calculate the download path for the cloud file
117         public string GetDownloadPath()
118         {
119             if (CloudFile == null)
120                 return String.Empty;
121             var filePath = CloudFile.RelativeUrlToFilePath(AccountInfo.UserName);
122             return Path.Combine(AccountInfo.AccountPath, filePath);
123         }
124
125         public override string ToString()
126         {
127             return String.Format("{0}:{1}->{2}", Action, LocalFile.FullName, CloudFile.Name);
128         }
129
130         protected static ObjectInfo CreateObjectInfoFor(AccountInfo accountInfo, FileSystemInfo fileInfo)
131         {
132             if(accountInfo==null)
133                 throw new ArgumentNullException("accountInfo");
134             if(fileInfo==null)
135                 throw new ArgumentNullException("fileInfo");
136             Contract.Ensures(Contract.Result<ObjectInfo>()!=null);
137             Contract.EndContractBlock();
138
139             var capitalizedFileInfo = fileInfo.WithProperCapitalization();
140             var fullLocalName = capitalizedFileInfo.FullName;
141             var othersPath = Path.Combine(accountInfo.AccountPath, FolderConstants.OthersFolder);
142
143             ObjectInfo objectInfo;
144
145             var isShared = fullLocalName.StartsWith(othersPath, StringComparison.InvariantCultureIgnoreCase);
146             if (isShared)
147             {                
148                 var pathRelativeToOther = fullLocalName.Substring(othersPath.Length + 1);
149                 var otherParts = pathRelativeToOther.Split('\\');
150                 var otherName = otherParts[0];
151                 var otherContainer = otherParts[1];
152                 objectInfo=new ObjectInfo
153                            {
154                                Account = otherName, 
155                                Container = otherContainer, 
156                                Name = String.Join("/", otherParts.Splice(2))
157                            };
158             }
159             else
160                 objectInfo=new ObjectInfo(accountInfo.AccountPath, accountInfo.UserName, fileInfo);
161             
162             objectInfo.Content_Type= (fileInfo is DirectoryInfo)
163                                     ?   "appication/directory"
164                                     :   "application/octet-stream";
165             return objectInfo;
166         }
167     }    
168
169     public class CloudDownloadAction:CloudAction
170     {
171         public CloudDownloadAction(AccountInfo accountInfo, ObjectInfo cloudFile)
172             :base(accountInfo,CloudActionType.DownloadUnconditional)
173         {            
174             if (String.IsNullOrWhiteSpace(cloudFile.Container))
175                 throw new ArgumentException("CloudFile.Container","cloudFile");
176             Contract.EndContractBlock();
177
178             CloudFile = cloudFile;
179         }
180
181         [ContractInvariantMethod]
182         private void Invariants()
183         {
184             Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
185         }
186
187         public override string ToString()
188         {
189             return String.Format("{0}: _ <- {1}", Action, CloudFile.Name);
190         }
191         
192     }
193     public class CloudDeleteAction:CloudAction
194     {
195         public CloudDeleteAction(AccountInfo accountInfo,FileSystemInfo fileInfo, FileState fileState)
196             : this(accountInfo,fileInfo,CreateObjectInfoFor(accountInfo, fileInfo),fileState)
197         {            
198         }
199
200         public CloudDeleteAction(AccountInfo accountInfo, FileSystemInfo fileInfo,ObjectInfo cloudFile, FileState fileState) 
201             : base(accountInfo,CloudActionType.DeleteCloud)
202         {
203             CloudFile = cloudFile;
204             LocalFile = fileInfo;
205             FileState = fileState;
206         }
207
208         public CloudDeleteAction(CloudAction action)
209             : this(action.AccountInfo,action.LocalFile,action.CloudFile,action.FileState)
210         {}
211
212         [ContractInvariantMethod]
213         private void Invariants()
214         {
215             Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
216         }
217
218         public override string ToString()
219         {
220             return String.Format("{0}: _ ->{1}", Action, CloudFile.Name);
221         }
222
223     }
224
225     public class CloudUploadAction:CloudAction
226     {
227         public CloudUploadAction(AccountInfo accountInfo, FileSystemInfo fileInfo, FileState state, int blockSize, string algorithm)
228             : base(accountInfo, CloudActionType.UploadUnconditional,fileInfo,CreateObjectInfoFor(accountInfo,fileInfo),state,blockSize,algorithm)             
229         {
230         }
231
232         [ContractInvariantMethod]
233         private void Invariants()
234         {
235             Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
236         }
237
238     }
239
240     public class CloudMoveAction:CloudAction
241     {
242         public ObjectInfo OldCloudFile { get; set; }
243
244         public FileSystemInfo OldLocalFile { get; set; }
245
246         public CloudMoveAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo oldFile, FileSystemInfo newFile)
247             :base(accountInfo,action)
248         {
249             LocalFile = newFile;
250             CloudFile = CreateObjectInfoFor(accountInfo, newFile);
251             
252             OldLocalFile = oldFile;
253             OldCloudFile = CreateObjectInfoFor(accountInfo, oldFile);
254
255             //This is a rename operation, a hash will not be used
256             TreeHash = new Lazy<TreeHash>(() => Network.TreeHash.Empty, LazyThreadSafetyMode.ExecutionAndPublication);
257         }
258
259         public override string ToString()
260         {
261             return String.Format("{0}:{1}->{2}", Action, OldCloudFile.Name, CloudFile.Name);
262         }
263
264     }
265
266 }