Replaced object load and update with direct HQL execution to resolve database locks...
[pithos-ms-client] / trunk / Pithos.Core / Agents / StatusAgent.cs
index 1639e76..de7af7b 100644 (file)
@@ -1,21 +1,18 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel.Composition;
+using System.Data.SQLite;
 using System.Diagnostics;
 using System.Diagnostics.Contracts;
 using System.IO;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
-using System.Threading.Tasks.Dataflow;
 using Castle.ActiveRecord;
 using Castle.ActiveRecord.Framework.Config;
 using Pithos.Interfaces;
 using Pithos.Network;
 using log4net;
-using log4net.Appender;
-using log4net.Config;
-using log4net.Layout;
 
 namespace Pithos.Core.Agents
 {
@@ -25,8 +22,7 @@ namespace Pithos.Core.Agents
         [System.ComponentModel.Composition.Import]
         public IPithosSettings Settings { get; set; }
 
-        //private Agent<Action> _persistenceAgent;
-        private ActionBlock<Action> _persistenceAgent;
+        private Agent<Action> _persistenceAgent;
 
 
         private static readonly ILog Log = LogManager.GetLogger("StatusAgent");
@@ -76,16 +72,33 @@ namespace Pithos.Core.Agents
 
         public void StartProcessing(CancellationToken token)
         {
-            _persistenceAgent = new ActionBlock<Action>(async action=>
+            _persistenceAgent = Agent<Action>.Start(queue =>
             {
-                    try
-                    {
-                        await TaskEx.Run(action);
-                    }
-                    catch (Exception ex)
+                Action loop = null;
+                loop = () =>
+                {
+                    var job = queue.Receive();
+                    job.ContinueWith(t =>
                     {
-                        Log.ErrorFormat("[ERROR] STATE \n{0}",ex);
-                    }
+                        var action = job.Result;
+                        try
+                        {
+                            action();
+                        }
+                        catch (SQLiteException ex)
+                        {
+                            Log.ErrorFormat("[ERROR] SQL \n{0}", ex);
+                        }
+                        catch (Exception ex)
+                        {
+                            Log.ErrorFormat("[ERROR] STATE \n{0}", ex);
+                        }
+// ReSharper disable AccessToModifiedClosure
+                        queue.DoAsync(loop);
+// ReSharper restore AccessToModifiedClosure
+                    });
+                };
+                loop();
             });
             
         }
@@ -94,7 +107,7 @@ namespace Pithos.Core.Agents
 
         public void Stop()
         {
-            _persistenceAgent.Complete();            
+            _persistenceAgent.Stop();            
         }
        
 
@@ -118,7 +131,7 @@ namespace Pithos.Core.Agents
                              select new {state.Id, state.FilePath}).ToList();
             //and check each one
             var missingStates= (from path in statePaths
-                               where !File.Exists(path.FilePath)
+                                where !File.Exists(path.FilePath) && !Directory.Exists(path.FilePath)
                                select path.Id).ToList();
             //Finally, retrieve the states that correspond to the deleted files            
             var deletedFiles = from state in fileStates 
@@ -135,7 +148,7 @@ namespace Pithos.Core.Agents
                 {
                     //This is a new file
                     var fullPath = pair.File.FullName.ToLower();
-                    var createState = FileState.CreateForAsync(fullPath, this.BlockSize, this.BlockHash);
+                    var createState = FileState.CreateForAsync(fullPath, BlockSize, BlockHash);
                     createState.ContinueWith(state => _persistenceAgent.Post(state.Result.Create));
                 }                
                 else if (file == null)
@@ -194,8 +207,8 @@ namespace Pithos.Core.Agents
         }
 
 
-        private string _pithosDataPath;
-       
+        private readonly string _pithosDataPath;
+
 
         public FileOverlayStatus GetFileOverlayStatus(string path)
         {
@@ -207,6 +220,7 @@ namespace Pithos.Core.Agents
 
             try
             {
+
                 var status = from state in  FileState.Queryable 
                                  where state.FilePath ==path.ToLower()
                                  select state.OverlayStatus;
@@ -230,30 +244,7 @@ namespace Pithos.Core.Agents
             _persistenceAgent.Post(() => FileState.StoreOverlayStatus(path.ToLower(),overlayStatus));
         }
 
-        /*public void RemoveFileOverlayStatus(string path)
-        {
-            if (String.IsNullOrWhiteSpace(path))
-                throw new ArgumentNullException("path");
-            if (!Path.IsPathRooted(path))
-                throw new ArgumentException("The path must be rooted", "path");
-            Contract.EndContractBlock();
-
-            _persistenceAgent.Post(() =>
-                InnerRemoveFileOverlayStatus(path));
-        }
-
-        private static void InnerRemoveFileOverlayStatus(string path)
-        {
-            if (String.IsNullOrWhiteSpace(path))
-                throw new ArgumentNullException("path");
-            if (!Path.IsPathRooted(path))
-                throw new ArgumentException("The path must be rooted", "path");
-            Contract.EndContractBlock();
-
-            FileState.DeleteByFilePath(path);            
-        }*/
-
-        public void RenameFileOverlayStatus(string oldPath, string newPath)
+       /* public void RenameFileOverlayStatus(string oldPath, string newPath)
         {
             if (String.IsNullOrWhiteSpace(oldPath))
                 throw new ArgumentNullException("oldPath");
@@ -266,7 +257,7 @@ namespace Pithos.Core.Agents
             Contract.EndContractBlock();
 
             _persistenceAgent.Post(() =>FileState.RenameState(oldPath, newPath));
-        }
+        }*/
 
         public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus)
         {
@@ -313,18 +304,7 @@ namespace Pithos.Core.Agents
                     state.FileStatus = FileStatus.Unchanged;
                     state.OverlayStatus = FileOverlayStatus.Normal;
                     
-                    //Create a list of tags from the ObjectInfo's tag dictionary
-                    //Make sure to bind each tag to its parent state so we don't have to save each tag separately
-                    //state.Tags = (from pair in objectInfo.Tags
-                    //                select
-                    //                    new FileTag
-                    //                        {
-                    //                            FileState = state,
-                    //                            Name = pair.Key,
-                    //                            Value = pair.Value
-                    //                        }
-                    //            ).ToList();
-
+                  
                     //Do the save
                     state.Save();
                 }
@@ -365,15 +345,8 @@ namespace Pithos.Core.Agents
             if (!Path.IsPathRooted(path))
                 throw new ArgumentException("The path must be rooted", "path");
             Contract.EndContractBlock();
-
-            //TODO:SHOULDN'T need both clear file status and remove overlay status
-            _persistenceAgent.Post(() =>
-            {
-                using (new SessionScope())
-                {
-                    FileState.DeleteByFilePath(path);
-                }
-            });   
+            
+            _persistenceAgent.Post(() => FileState.DeleteByFilePath(path));   
         }
 
         public void UpdateFileChecksum(string path, string checksum)