Modified loggers to use their enclosing class
[pithos-ms-client] / trunk / Pithos.Core / FileState.cs
index 34d8559..5fbacbd 100644 (file)
@@ -1,55 +1,61 @@
-// -----------------------------------------------------------------------
-// <copyright file="FileState.cs" company="GRNet">
-// Copyright 2011 GRNET S.A. All rights reserved.
-// 
-// Redistribution and use in source and binary forms, with or
-// without modification, are permitted provided that the following
-// conditions are met:
-// 
-//   1. Redistributions of source code must retain the above
-//      copyright notice, this list of conditions and the following
-//      disclaimer.
-// 
-//   2. Redistributions in binary form must reproduce the above
-//      copyright notice, this list of conditions and the following
-//      disclaimer in the documentation and/or other materials
-//      provided with the distribution.
-// 
-// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
-// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
-// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
-// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-// POSSIBILITY OF SUCH DAMAGE.
-// 
-// The views and conclusions contained in the software and
-// documentation are those of the authors and should not be
-// interpreted as representing official policies, either expressed
-// or implied, of GRNET S.A.
-// </copyright>
-// -----------------------------------------------------------------------
-
-
+#region
+/* -----------------------------------------------------------------------
+ * <copyright file="FileState.cs" company="GRNet">
+ * 
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ * </copyright>
+ * -----------------------------------------------------------------------
+ */
+#endregion
 using System.Diagnostics.Contracts;
 using System.IO;
+using System.Reflection;
 using System.Threading.Tasks;
 using Castle.ActiveRecord;
 using Castle.ActiveRecord.Framework;
+using Castle.ActiveRecord.Queries;
+using NHibernate.Criterion;
 using Pithos.Core.Agents;
 using Pithos.Interfaces;
+using Pithos.Network;
 using log4net;
 
 namespace Pithos.Core
 {
     using System;
-    using System.Collections.Generic;
-    using System.Linq;
+    using System.Collections.Generic;    
 
     /// <summary>
     /// TODO: Update summary.
@@ -57,20 +63,17 @@ namespace Pithos.Core
     [ActiveRecord]
     public class FileState : ActiveRecordLinqBase<FileState>
     {
-        private static readonly ILog Log = LogManager.GetLogger("FileState");
+        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
 
-        private string _filePath;
         private IList<FileTag> _tags = new List<FileTag>();
 
         [PrimaryKey(PrimaryKeyType.Guid)]
         public Guid Id { get; set; }
 
+        
         [Property(Unique = true, UniqueKey = "IX_FileState_FilePath")]
-        public string FilePath
-        {
-            get { return _filePath; }
-            set { _filePath = value.ToLower(); }
-        }
+        public string FilePath { get; set; }
 
         [Property]
         public FileOverlayStatus OverlayStatus { get; set; }
@@ -98,6 +101,8 @@ namespace Pithos.Core
         [Property]
         public bool ShareWrite { get; set; }
 
+        [Property]
+        public bool IsFolder{ get; set; }
 
         [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true, Inverse = true)]
         public IList<FileTag> Tags
@@ -106,8 +111,31 @@ namespace Pithos.Core
             set { _tags = value; }
         }
 
+        [Property]
+        public DateTime Modified { get; set; }
+
 
-        public static FileState FindByFilePath(string absolutePath)
+        public FileSystemInfo GetFileSystemInfo()
+        {
+            if (String.IsNullOrWhiteSpace(FilePath))
+                throw new InvalidOperationException();
+            Contract.EndContractBlock();
+
+            return Directory.Exists(FilePath) ?
+                (FileSystemInfo)new DirectoryInfo(FilePath)
+                : new FileInfo(FilePath);
+        }
+
+        public string GetRelativeUrl(AccountInfo accountInfo)
+        {
+            if (accountInfo==null)
+                throw new ArgumentNullException("accountInfo");
+            Contract.EndContractBlock();
+
+            var fsi=GetFileSystemInfo();
+            return fsi.AsRelativeUrlTo(accountInfo.AccountPath);
+        }
+        /*public static FileState FindByFilePath(string absolutePath)
         {
             if (string.IsNullOrWhiteSpace(absolutePath))
                 throw new ArgumentNullException("absolutePath");
@@ -117,7 +145,7 @@ namespace Pithos.Core
 
                 
 
-                return Queryable.FirstOrDefault(s => s.FilePath == absolutePath.ToLower());
+                return Queryable.FirstOrDefault(s => s.FilePath == absolutePath);
             }
             catch (Exception ex)
             {
@@ -126,7 +154,7 @@ namespace Pithos.Core
             }
 
 
-        }
+        }*/
 
        /* public static void DeleteByFilePath(string absolutePath)
         {
@@ -138,7 +166,7 @@ namespace Pithos.Core
                         {
                             const string hqlDelete = "delete FileState where FilePath = :path";
                             var deletedEntities = session.CreateQuery(hqlDelete)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .ExecuteUpdate();
                             return deletedEntities;
                         }, null);
@@ -153,18 +181,19 @@ namespace Pithos.Core
 
             ExecuteWithRetry((session, instance) =>
                         {
-                            const string hqlUpdate = "update FileState set FileStatus= :status where FilePath = :path  ";
+                            const string hqlUpdate = "update FileState set FileStatus= :status where FilePath = :path ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .SetEnum("status", newStatus)
                                 .ExecuteUpdate();
                             if (updatedEntities == 0)
                             {
                                 var newState = new FileState
                                                    {
-                                                       FilePath = absolutePath.ToLower(),
+                                                       FilePath = absolutePath,
                                                        Id = Guid.NewGuid(),
-                                                       FileStatus = newStatus
+                                                       FileStatus = newStatus,
+                                                       IsFolder=Directory.Exists(absolutePath)
                                                    };
                                 newState.CreateAndFlush();
                             }
@@ -182,10 +211,10 @@ namespace Pithos.Core
             ExecuteWithRetry((session, instance) =>
                         {
                             const string hqlUpdate =
-                                "update FileState set OverlayStatus= :status where FilePath = :path  ";
-                            var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
-                                .SetEnum("status", newStatus)
+                                "update FileState set OverlayStatus= :status where FilePath = :path ";
+                            var updatedEntities = session.CreateQuery(hqlUpdate)                                
+                                .SetString("path", absolutePath)
+                                .SetEnum("status", newStatus)                                
                                 .ExecuteUpdate();
                             if (updatedEntities == 0)
                             {
@@ -193,7 +222,8 @@ namespace Pithos.Core
                                                    {
                                                        FilePath = absolutePath,
                                                        Id = Guid.NewGuid(),
-                                                       OverlayStatus = newStatus
+                                                       OverlayStatus = newStatus,
+                                                       IsFolder=Directory.Exists(absolutePath)
                                                    };
                                 newState.CreateAndFlush();
                             }
@@ -214,7 +244,7 @@ namespace Pithos.Core
                             const string hqlUpdate =
                                 "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path  ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .SetEnum("fileStatus", fileStatus)
                                 .SetEnum("overlayStatus", overlayStatus)
                                 .ExecuteUpdate();
@@ -236,7 +266,7 @@ namespace Pithos.Core
                             const string hqlUpdate =
                                 "update FileState set FileStatus= :fileStatus where FilePath = :path  ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .SetEnum("fileStatus", fileStatus)
                                 .ExecuteUpdate();
                             return updatedEntities;
@@ -254,10 +284,10 @@ namespace Pithos.Core
             ExecuteWithRetry((session, instance) =>
                         {
                             const string hqlUpdate =
-                                "update FileState set FilePath= :newPath where FilePath = :oldPath  ";
+                                "update FileState set FilePath= :newPath where FilePath = :oldPath ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("oldPath", oldPath.ToLower())
-                                .SetString("newPath", newPath.ToLower())
+                                .SetString("oldPath", oldPath)
+                                .SetString("newPath", newPath)
                                 .ExecuteUpdate();
                             return updatedEntities;
                         }, null);
@@ -287,9 +317,9 @@ namespace Pithos.Core
 
             ExecuteWithRetry((session, instance) =>
                         {
-                            const string hqlUpdate = "update FileState set Checksum= :checksum where FilePath = :path  ";
+                            const string hqlUpdate = "update FileState set Checksum= :checksum where FilePath = :path ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .SetString("checksum", checksum)
                                 .ExecuteUpdate();
                             return updatedEntities;
@@ -320,8 +350,8 @@ namespace Pithos.Core
                                 const string hqlUpdate =
                                     "update FileState set FilePath = replace(FilePath,:oldPath,:newPath) where FilePath like :oldPath || '%' ";
                                 var renames = session.CreateQuery(hqlUpdate)
-                                    .SetString("oldPath", oldPath.ToLower())
-                                    .SetString("newPath", newPath.ToLower())
+                                    .SetString("oldPath", oldPath)
+                                    .SetString("newPath", newPath)
                                     .ExecuteUpdate();
                                 return renames;
                             }, null);
@@ -338,7 +368,7 @@ namespace Pithos.Core
 
             var fileState = new FileState
                                 {
-                                    FilePath = filePath.ToLower(),
+                                    FilePath = filePath,
                                     OverlayStatus = FileOverlayStatus.Unversioned,
                                     FileStatus = FileStatus.Created,
                                     Id = Guid.NewGuid()
@@ -380,6 +410,7 @@ namespace Pithos.Core
                     using (new SessionScope())
                     {
                         Execute(call, state);
+                        return;
                     }
                 }
                 catch (ActiveRecordException )
@@ -389,6 +420,48 @@ namespace Pithos.Core
                         throw;
                 }
         }
+
+        /// <summary>
+        /// Mark Unversioned all FileState rows from the database whose path
+        /// starts with one of the removed paths
+        /// </summary>
+        /// <param name="removed"></param>
+        public static void UnversionPaths(List<string> removed)
+        {
+            if (removed == null)
+                return;
+            if (removed.Count == 0)
+                return;
+
+            //Create a disjunction (list of OR statements
+            var disjunction = new Disjunction();            
+            foreach (var path in removed)
+            {
+                //with the restriction FileState.FilePath like '@path%'
+                disjunction.Add(Restrictions.On<FileState>(s => s.FilePath)
+                    .IsLike(path, MatchMode.Start));
+            }
+
+            //Generate a query from the disjunction
+            var query=QueryOver.Of<FileState>().Where(disjunction);
+                        
+            ExecuteWithRetry((session,instance)=>
+                                 {
+                                     using (var t=session.BeginTransaction())
+                                     {
+                                         var states = query.GetExecutableQueryOver(session).List();
+                                         foreach (var state in states)
+                                         {
+                                             state.FileStatus = FileStatus.Unversioned;
+                                             state.OverlayStatus = FileOverlayStatus.Unversioned;
+                                             state.Update();
+                                         }
+                                         t.Commit();
+                                     }
+                                     return null;
+                                 },null);
+        }
+
     }
 
     [ActiveRecord("Tags")]