c14d3d8eb339ca837b56c4cdf6db2c505d7ff387
[pithos-ms-client] / trunk / Pithos.Core / Agents / CloudTransferAction.cs
1 using System;
2 using System.Diagnostics.Contracts;
3 using System.IO;
4 using System.Threading;
5 using Pithos.Interfaces;
6 using Pithos.Network;
7
8 namespace Pithos.Core.Agents
9 {
10     public enum CloudActionType
11     {
12         MustSynch,
13         UploadUnconditional,
14         DownloadUnconditional,
15         DeleteLocal,
16         DeleteCloud,
17         RenameCloud
18     }
19
20     public class CloudAction
21     {
22         public AccountInfo AccountInfo { get; set; }
23         public CloudActionType Action { get; set; }
24         public FileSystemInfo LocalFile { get; set; }
25         public ObjectInfo CloudFile { get; set; }
26         public FileState FileState { get; set; }
27         public string Container { get; set; }
28
29         public readonly DateTime Created = DateTime.Now;
30
31
32         public Lazy<string> LocalHash { get; protected set; }
33         private Lazy<string> _topHash;
34         public Lazy<string> TopHash
35         {
36             get { return _topHash; }
37             set { _topHash = value; }
38         }
39
40
41         [ContractInvariantMethod]
42         private void Invariants()
43         {
44             Contract.Invariant(AccountInfo!=null);
45         }
46
47         protected CloudAction(AccountInfo accountInfo,CloudActionType action)
48         {
49             if (accountInfo==null)
50                 throw new ArgumentNullException("accountInfo");
51             Contract.EndContractBlock();
52
53             Action = action;
54             AccountInfo = accountInfo;
55         }
56
57         public CloudAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo localFile, ObjectInfo cloudFile, FileState state, int blockSize, string algorithm)
58             : this(accountInfo,action)
59         {
60             LocalFile = localFile.WithProperCapitalization();
61             CloudFile = cloudFile;
62             FileState = state;
63             if (LocalFile != null)
64             {
65
66                 LocalHash = new Lazy<string>(() => LocalFile.CalculateHash(blockSize,algorithm),
67                                              LazyThreadSafetyMode.ExecutionAndPublication);
68             }
69         }
70
71         //Calculate the download path for the cloud file
72         public string GetDownloadPath()
73         {
74             if (CloudFile == null)
75                 return String.Empty;
76             var filePath = CloudFile.RelativeUrlToFilePath(AccountInfo.UserName);
77             return Path.Combine(AccountInfo.AccountPath, filePath);
78         }
79
80         public override string ToString()
81         {
82             return String.Format("{0}:{1}->{2}", this.Action, this.LocalFile.FullName, this.CloudFile.Name);
83         }
84
85         protected static ObjectInfo CreateObjectInfoFor(AccountInfo accountInfo, FileSystemInfo fileInfo)
86         {
87             Contract.Requires(accountInfo!=null);
88             Contract.Requires(fileInfo!=null);
89             Contract.Ensures(Contract.Result<ObjectInfo>()!=null);
90
91             var capitalizedFileInfo = fileInfo.WithProperCapitalization();
92             var fullLocalName = capitalizedFileInfo.FullName;
93             var othersPath = Path.Combine(accountInfo.AccountPath, FolderConstants.OthersFolder);
94             
95             var isShared = fullLocalName.StartsWith(othersPath, StringComparison.InvariantCultureIgnoreCase);
96             if (isShared)
97             {                
98                 var pathRelativeToOther = fullLocalName.Substring(othersPath.Length + 1);
99                 var otherParts = pathRelativeToOther.Split('\\');
100                 var otherName = otherParts[0];
101                 var otherContainer = otherParts[1];
102                 return new ObjectInfo
103                            {
104                                Account = otherName, 
105                                Container = otherContainer, 
106                                Name = String.Join("/", otherParts.Splice(2))
107                            };
108             }
109             return new ObjectInfo(accountInfo.AccountPath, accountInfo.UserName, fileInfo);
110         }
111     }    
112
113     public class CloudDownloadAction:CloudAction
114     {
115         public CloudDownloadAction(AccountInfo accountInfo, ObjectInfo cloudFile)
116             :base(accountInfo,CloudActionType.DownloadUnconditional)
117         {            
118             if (String.IsNullOrWhiteSpace(cloudFile.Container))
119                 throw new ArgumentException("CloudFile.Container","cloudFile");
120             Contract.EndContractBlock();
121
122             CloudFile = cloudFile;
123         }
124
125         [ContractInvariantMethod]
126         private void Invariants()
127         {
128             Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
129         }
130
131         public override string ToString()
132         {
133             return String.Format("{0}: _ <- {1}", this.Action, this.CloudFile.Name);
134         }
135         
136     }
137     public class CloudDeleteAction:CloudAction
138     {
139         public CloudDeleteAction(AccountInfo accountInfo,FileSystemInfo fileInfo, FileState fileState)
140             : this(accountInfo,fileInfo,CreateObjectInfoFor(accountInfo, fileInfo),fileState)
141         {            
142         }
143
144         public CloudDeleteAction(AccountInfo accountInfo, FileSystemInfo fileInfo,ObjectInfo cloudFile, FileState fileState) 
145             : base(accountInfo,CloudActionType.DeleteCloud)
146         {
147             CloudFile = cloudFile;
148             LocalFile = fileInfo;
149             FileState = fileState;
150         }
151
152         public CloudDeleteAction(CloudAction action)
153             : this(action.AccountInfo,action.LocalFile,action.CloudFile,action.FileState)
154         {}
155
156         [ContractInvariantMethod]
157         private void Invariants()
158         {
159             Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
160         }
161
162         public override string ToString()
163         {
164             return String.Format("{0}: _ ->{1}", this.Action, this.CloudFile.Name);
165         }
166
167     }
168
169     public class CloudUploadAction:CloudAction
170     {
171         public CloudUploadAction(AccountInfo accountInfo, FileSystemInfo fileInfo, FileState state, int blockSize, string algorithm)
172             : base(accountInfo, CloudActionType.UploadUnconditional,fileInfo,CreateObjectInfoFor(accountInfo,fileInfo),state,blockSize,algorithm)             
173         {
174         }
175
176         [ContractInvariantMethod]
177         private void Invariants()
178         {
179             Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
180         }
181
182     }
183
184     public class CloudMoveAction:CloudAction
185     {
186         public ObjectInfo OldCloudFile { get; set; }
187
188         public FileSystemInfo OldLocalFile { get; set; }
189
190         public CloudMoveAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo oldFile, FileSystemInfo newFile)
191             :base(accountInfo,action)
192         {
193             LocalFile = newFile;
194             CloudFile = CreateObjectInfoFor(accountInfo, newFile);
195             
196             OldLocalFile = oldFile;
197             OldCloudFile = CreateObjectInfoFor(accountInfo, oldFile);
198
199             //This is a rename operation, a hash will not be used
200             LocalHash = new Lazy<string>(() => String.Empty, LazyThreadSafetyMode.ExecutionAndPublication);
201         }
202
203         public override string ToString()
204         {
205             return String.Format("{0}:{1}->{2}", this.Action, OldCloudFile.Name, CloudFile.Name);
206         }
207
208     }
209
210 }