// </copyright>
// -----------------------------------------------------------------------
+using System.Diagnostics.Contracts;
+using System.IO;
using System.Threading.Tasks;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;
+using Castle.ActiveRecord.Queries;
+using NHibernate.Engine;
+using Pithos.Core.Agents;
using Pithos.Interfaces;
+using Pithos.Network;
namespace Pithos.Core
{
private string _filePath;
private IList<FileTag> _tags=new List<FileTag>();
+ [PrimaryKey(PrimaryKeyType.Guid)]
+ public Guid Id { get; set; }
- [PrimaryKey]
+ [Property(Unique=true,UniqueKey="IX_FileState_FilePath")]
public string FilePath
{
get { return _filePath; }
[Property]
public string Checksum { get; set; }
- [HasMany(Cascade=ManyRelationCascadeEnum.AllDeleteOrphan,Lazy=true)]
+/*
+ [Property]
+ public string TopHash { get; set; }
+*/
+
+ [Property]
+ public long? Version { get; set; }
+
+ [Property]
+ public DateTime? VersionTimeStamp { get; set; }
+
+
+ [Property]
+ public bool IsShared { get; set; }
+
+ [Property]
+ public string SharedBy { get; set; }
+
+ [Property]
+ public bool ShareWrite { get; set; }
+
+
+ [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true,Inverse=true)]
public IList<FileTag> Tags
{
get { return _tags; }
set { _tags=value;}
}
- [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true)]
- public IList<FileHash> Hashes { get; set; }
+// [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true)]
+// public IList<FileHash> Hashes { get; set; }
+
+// [Property]
+// public byte[] HashmapHash { get; set; }
+
+ public static FileState FindByFilePath(string absolutePath)
+ {
+ if (string.IsNullOrWhiteSpace(absolutePath))
+ throw new ArgumentNullException("absolutePath");
+ Contract.EndContractBlock();
+ return Queryable.FirstOrDefault(s => s.FilePath == absolutePath.ToLower());
+ }
- public FileState()
+ public static void DeleteByFilePath(string absolutePath)
{
+ if(string.IsNullOrWhiteSpace(absolutePath))
+ throw new ArgumentNullException("absolutePath");
+ Contract.EndContractBlock();
+
+ FileState.Execute((session, instance) =>
+ {
+ const string hqlDelete = "delete FileState where FilePath = :path";
+ var deletedEntities = session.CreateQuery(hqlDelete)
+ .SetString("path", absolutePath.ToLower())
+ .ExecuteUpdate();
+ return null;
+ },null);
}
- private static int BLOCK_SIZE = 4194304;
+ public static void ChangeRootPath(string oldPath,string newPath)
+ {
+ if (String.IsNullOrWhiteSpace(oldPath))
+ throw new ArgumentNullException("oldPath");
+ if (!Path.IsPathRooted(oldPath))
+ throw new ArgumentException("oldPath must be an absolute path", "oldPath");
+ if (string.IsNullOrWhiteSpace(newPath))
+ throw new ArgumentNullException("newPath");
+ if (!Path.IsPathRooted(newPath))
+ throw new ArgumentException("newPath must be an absolute path", "newPath");
+ Contract.EndContractBlock();
+
+ //Ensure the paths end with the same character
+ if (!oldPath.EndsWith("\\"))
+ oldPath = oldPath + "\\";
+ if (!newPath.EndsWith("\\"))
+ newPath = newPath + "\\";
+
+ using (new TransactionScope())
+ {
+ Execute((session, instance) =>
+ {
+ const string hqlUpdate =
+ "update FileState set FilePath = replace(FilePath,:oldPath,:newPath) where FilePath like :oldPath || '%' ";
+ var result=session.CreateQuery(hqlUpdate)
+ .SetString("oldPath", oldPath.ToLower())
+ .SetString("newPath", newPath.ToLower())
+ .ExecuteUpdate();
+ return null;
+ }, null);
+ }
+ }
- public static Task<FileState> CreateForAsync(string filePath)
+ public static Task<FileState> CreateForAsync(string filePath,int blockSize,string algorithm)
{
+ if (blockSize <= 0)
+ throw new ArgumentOutOfRangeException("blockSize");
+ if (String.IsNullOrWhiteSpace(algorithm))
+ throw new ArgumentNullException("algorithm");
+ Contract.EndContractBlock();
+
+
var fileState = new FileState
{
FilePath = filePath,
OverlayStatus = FileOverlayStatus.Unversioned,
- FileStatus = FileStatus.Created
+ FileStatus = FileStatus.Created,
+ Id=Guid.NewGuid()
};
+
+
+ return fileState.UpdateHashesAsync(blockSize,algorithm);
+ }
+
+ public Task<FileState> UpdateHashesAsync(int blockSize,string algorithm)
+ {
+ if (blockSize<=0)
+ throw new ArgumentOutOfRangeException("blockSize");
+ if (String.IsNullOrWhiteSpace(algorithm))
+ throw new ArgumentNullException("algorithm");
+ Contract.EndContractBlock();
+ //Skip updating the hash for folders
+ if (Directory.Exists(FilePath))
+ return Task.Factory.FromResult(this);
+
+ var results = Task.Factory.StartNew(() =>
+ {
+ var info = new FileInfo(FilePath);
+ return info.CalculateHash(blockSize, algorithm);
+ });
+
+ var state=results.Then(hash =>
+ {
+ Checksum = hash;
+ return Task.Factory.FromResult(this);
+ });
- return Task.Factory.StartNew(()=> {
- fileState.Checksum = Signature.CalculateHash(fileState.FilePath);
- })
- .ContinueWith(_=> Signature.CalculateBlockHashesAsync(filePath, BLOCK_SIZE)).Unwrap()
- .ContinueWith(t =>
- {
- fileState.Hashes = t.Result;
- }).ContinueWith(t =>
- {
- fileState.HashmapHash = Signature.CalculateHashmapHash(fileState.Hashes);
- }).ContinueWith(t=> fileState);
- //return fileState;
+ return state;
}
-
- public byte[] HashmapHash { get; set; }
}
- [ActiveRecord]
+ [ActiveRecord("Tags")]
public class FileTag : ActiveRecordLinqBase<FileTag>
{
[PrimaryKey]
- public string FilePath { get; set; }
+ public int Id { get; set; }
+
+ [Property]
+ public string Name { get; set; }
[Property]
public string Value { get; set; }
- [BelongsTo("FilePath")]
+ [BelongsTo("FileStateId")]
public FileState FileState { get; set; }
}
- [ActiveRecord]
+ /* [ActiveRecord("hashes")]
public class FileHash : ActiveRecordLinqBase<FileHash>
{
[PrimaryKey]
- public string FilePath { get; set; }
+ public int Id { get; set; }
+
+ [Property]
+ public int Order { get; set; }
[Property]
public byte[] Value { get; set; }
- [BelongsTo("FilePath")]
+ [BelongsTo("FileStateID")]
public FileState FileState { get; set; }
- }
+ }*/
}