1 // -----------------------------------------------------------------------
2 // <copyright file="FileState.cs" company="Microsoft">
3 // TODO: Update copyright text.
5 // -----------------------------------------------------------------------
7 using System.Diagnostics.Contracts;
9 using System.Threading.Tasks;
10 using Castle.ActiveRecord;
11 using Castle.ActiveRecord.Framework;
12 using Pithos.Core.Agents;
13 using Pithos.Interfaces;
19 using System.Collections.Generic;
23 /// TODO: Update summary.
26 public class FileState:ActiveRecordLinqBase<FileState>
28 private static readonly ILog Log = LogManager.GetLogger("FileState");
30 private string _filePath;
31 private IList<FileTag> _tags=new List<FileTag>();
33 [PrimaryKey(PrimaryKeyType.Guid)]
34 public Guid Id { get; set; }
36 [Property(Unique=true,UniqueKey="IX_FileState_FilePath")]
37 public string FilePath
39 get { return _filePath; }
40 set { _filePath = value.ToLower(); }
44 public FileOverlayStatus OverlayStatus { get; set; }
47 public FileStatus FileStatus { get; set; }
50 public string Checksum { get; set; }
54 public long? Version { get; set; }
57 public DateTime? VersionTimeStamp { get; set; }
61 public bool IsShared { get; set; }
64 public string SharedBy { get; set; }
67 public bool ShareWrite { get; set; }
70 [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true,Inverse=true)]
71 public IList<FileTag> Tags
78 public static FileState FindByFilePath(string absolutePath)
80 if (string.IsNullOrWhiteSpace(absolutePath))
81 throw new ArgumentNullException("absolutePath");
82 Contract.EndContractBlock();
85 return Queryable.FirstOrDefault(s => s.FilePath == absolutePath.ToLower());
89 Log.Error(ex.ToString());
96 public static void DeleteByFilePath(string absolutePath)
98 if(string.IsNullOrWhiteSpace(absolutePath))
99 throw new ArgumentNullException("absolutePath");
100 Contract.EndContractBlock();
102 Execute((session, instance) =>
104 const string hqlDelete = "delete FileState where FilePath = :path";
105 var deletedEntities = session.CreateQuery(hqlDelete)
106 .SetString("path", absolutePath.ToLower())
108 return deletedEntities;
113 public static void StoreFileStatus(string absolutePath, FileStatus newStatus)
115 if (string.IsNullOrWhiteSpace(absolutePath))
116 throw new ArgumentNullException("absolutePath");
117 Contract.EndContractBlock();
119 Execute((session, instance) =>
121 const string hqlUpdate = "update FileState set FileStatus= :status where FilePath = :path ";
122 var updatedEntities = session.CreateQuery(hqlUpdate)
123 .SetString("path", absolutePath.ToLower())
124 .SetEnum("status", newStatus)
126 if (updatedEntities == 0)
128 var newState = new FileState { FilePath = absolutePath, Id = Guid.NewGuid(), FileStatus = newStatus };
129 newState.CreateAndFlush();
136 public static void StoreOverlayStatus(string absolutePath, FileOverlayStatus newStatus)
138 if (string.IsNullOrWhiteSpace(absolutePath))
139 throw new ArgumentNullException("absolutePath");
140 Contract.EndContractBlock();
142 Execute((session, instance) =>
144 const string hqlUpdate = "update FileState set OverlayStatus= :status where FilePath = :path ";
145 var updatedEntities = session.CreateQuery(hqlUpdate)
146 .SetString("path", absolutePath.ToLower())
147 .SetEnum("status", newStatus)
149 if (updatedEntities == 0)
151 var newState = new FileState { FilePath = absolutePath, Id = Guid.NewGuid(), OverlayStatus = newStatus };
152 newState.CreateAndFlush();
159 public static void UpdateStatus(string absolutePath, FileStatus fileStatus, FileOverlayStatus overlayStatus)
161 if (string.IsNullOrWhiteSpace(absolutePath))
162 throw new ArgumentNullException("absolutePath");
163 Contract.EndContractBlock();
165 Execute((session, instance) =>
167 const string hqlUpdate = "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path ";
168 var updatedEntities = session.CreateQuery(hqlUpdate)
169 .SetString("path", absolutePath.ToLower())
170 .SetEnum("fileStatus", fileStatus)
171 .SetEnum("overlayStatus", overlayStatus)
173 return updatedEntities;
177 public static void UpdateStatus(string absolutePath, FileStatus fileStatus)
179 if (string.IsNullOrWhiteSpace(absolutePath))
180 throw new ArgumentNullException("absolutePath");
181 Contract.EndContractBlock();
183 Execute((session, instance) =>
185 const string hqlUpdate = "update FileState set FileStatus= :fileStatus where FilePath = :path ";
186 var updatedEntities = session.CreateQuery(hqlUpdate)
187 .SetString("path", absolutePath.ToLower())
188 .SetEnum("fileStatus", fileStatus)
190 return updatedEntities;
195 public static void RenameState(string oldPath, string newPath)
197 if (string.IsNullOrWhiteSpace(oldPath))
198 throw new ArgumentNullException("oldPath");
199 Contract.EndContractBlock();
201 Execute((session, instance) =>
203 const string hqlUpdate = "update FileState set FilePath= :newPath where FilePath = :oldPath ";
204 var updatedEntities = session.CreateQuery(hqlUpdate)
205 .SetString("oldPath", oldPath.ToLower())
206 .SetString("newPath", newPath.ToLower())
208 return updatedEntities;
213 public static void UpdateStatus(Guid id, FileStatus fileStatus)
215 Contract.EndContractBlock();
217 Execute((session, instance) =>
219 const string hqlUpdate = "update FileState set FileStatus= :fileStatus where Id = :id ";
220 var updatedEntities = session.CreateQuery(hqlUpdate)
222 .SetEnum("fileStatus", fileStatus)
224 return updatedEntities;
229 public static void UpdateChecksum(string absolutePath, string checksum)
231 if (string.IsNullOrWhiteSpace(absolutePath))
232 throw new ArgumentNullException("absolutePath");
233 Contract.EndContractBlock();
235 Execute((session, instance) =>
237 const string hqlUpdate = "update FileState set Checksum= :checksum where FilePath = :path ";
238 var updatedEntities = session.CreateQuery(hqlUpdate)
239 .SetString("path", absolutePath.ToLower())
240 .SetString("checksum", checksum)
242 return updatedEntities;
247 public static void ChangeRootPath(string oldPath,string newPath)
249 if (String.IsNullOrWhiteSpace(oldPath))
250 throw new ArgumentNullException("oldPath");
251 if (!Path.IsPathRooted(oldPath))
252 throw new ArgumentException("oldPath must be an absolute path", "oldPath");
253 if (string.IsNullOrWhiteSpace(newPath))
254 throw new ArgumentNullException("newPath");
255 if (!Path.IsPathRooted(newPath))
256 throw new ArgumentException("newPath must be an absolute path", "newPath");
257 Contract.EndContractBlock();
259 //Ensure the paths end with the same character
260 if (!oldPath.EndsWith("\\"))
261 oldPath = oldPath + "\\";
262 if (!newPath.EndsWith("\\"))
263 newPath = newPath + "\\";
265 using (new TransactionScope())
267 Execute((session, instance) =>
269 const string hqlUpdate =
270 "update FileState set FilePath = replace(FilePath,:oldPath,:newPath) where FilePath like :oldPath || '%' ";
271 var renames=session.CreateQuery(hqlUpdate)
272 .SetString("oldPath", oldPath.ToLower())
273 .SetString("newPath", newPath.ToLower())
280 public static Task<FileState> CreateForAsync(string filePath,int blockSize,string algorithm)
283 throw new ArgumentOutOfRangeException("blockSize");
284 if (String.IsNullOrWhiteSpace(algorithm))
285 throw new ArgumentNullException("algorithm");
286 Contract.EndContractBlock();
289 var fileState = new FileState
292 OverlayStatus = FileOverlayStatus.Unversioned,
293 FileStatus = FileStatus.Created,
298 return fileState.UpdateHashesAsync(blockSize,algorithm);
301 public Task<FileState> UpdateHashesAsync(int blockSize,string algorithm)
304 throw new ArgumentOutOfRangeException("blockSize");
305 if (String.IsNullOrWhiteSpace(algorithm))
306 throw new ArgumentNullException("algorithm");
307 Contract.EndContractBlock();
309 //Skip updating the hash for folders
310 if (Directory.Exists(FilePath))
311 return Task.Factory.FromResult(this);
313 var results = Task.Factory.StartNew(() =>
315 var info = new FileInfo(FilePath);
316 return info.CalculateHash(blockSize, algorithm);
319 var state=results.Then(hash =>
322 return Task.Factory.FromResult(this);
329 [ActiveRecord("Tags")]
330 public class FileTag : ActiveRecordLinqBase<FileTag>
333 public int Id { get; set; }
336 public string Name { get; set; }
339 public string Value { get; set; }
341 [BelongsTo("FileStateId")]
342 public FileState FileState { get; set; }