Renamed Others to others-shared
[pithos-ms-client] / trunk / Pithos.Core / FileState.cs
index f76164f..c1be0fd 100644 (file)
@@ -4,10 +4,16 @@
 // </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
 {
@@ -25,8 +31,10 @@ 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; }
@@ -42,77 +50,181 @@ namespace Pithos.Core
         [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; }
 
-    }
+    }*/
 
 
 }