New SQLite version
[pithos-ms-client] / trunk / Pithos.Core / Agents / StatusAgent.cs
index 8efda7b..4423f56 100644 (file)
@@ -55,9 +55,14 @@ using System.Threading.Tasks;
 using Castle.ActiveRecord;
 using Castle.ActiveRecord.Framework;
 using Castle.ActiveRecord.Framework.Config;
+using NHibernate.ByteCode.Castle;
+using NHibernate.Cfg;
+using NHibernate.Cfg.Loquacious;
+using NHibernate.Dialect;
 using Pithos.Interfaces;
 using Pithos.Network;
 using log4net;
+using Environment = System.Environment;
 
 namespace Pithos.Core.Agents
 {
@@ -76,10 +81,8 @@ namespace Pithos.Core.Agents
         public StatusAgent()
         {            
             var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
-            
-
 
-            _pithosDataPath = Path.Combine(appDataPath , "GRNET");
+            _pithosDataPath = Path.Combine(appDataPath , "GRNET\\PITHOS");
             if (!Directory.Exists(_pithosDataPath))
                 Directory.CreateDirectory(_pithosDataPath);
 
@@ -87,8 +90,10 @@ namespace Pithos.Core.Agents
 
             MigrateOldDb(dbPath, appDataPath);
 
+
             var source = GetConfiguration(_pithosDataPath);
             ActiveRecordStarter.Initialize(source,typeof(FileState),typeof(FileTag));
+            
             ActiveRecordStarter.UpdateSchema();
 
 
@@ -102,15 +107,23 @@ namespace Pithos.Core.Agents
 
         private static void MigrateOldDb(string dbPath, string appDataPath)
         {
-            Contract.Requires(!String.IsNullOrWhiteSpace(dbPath));
-            Contract.Requires(!String.IsNullOrWhiteSpace(appDataPath));
+            if(String.IsNullOrWhiteSpace(dbPath))
+                throw new ArgumentNullException("dbPath");
+            if(String.IsNullOrWhiteSpace(appDataPath))
+                throw new ArgumentNullException("appDataPath");
+            Contract.EndContractBlock();
 
             var oldDbPath = Path.Combine(appDataPath, "Pithos", "pithos.db");
             var oldDbInfo = new FileInfo(oldDbPath);
             if (oldDbInfo.Exists && !File.Exists(dbPath))
             {
+                Log.InfoFormat("Moving database from {0} to {1}",oldDbInfo.FullName,dbPath);
                 var oldDirectory = oldDbInfo.Directory;
-                oldDbInfo.MoveTo(dbPath);                
+                oldDbInfo.MoveTo(dbPath);
+                
+                if (Log.IsDebugEnabled)
+                    Log.DebugFormat("Deleting {0}",oldDirectory.FullName);
+                
                 oldDirectory.Delete(true);
             }
         }
@@ -556,7 +569,7 @@ namespace Pithos.Core.Agents
             _persistenceAgent.Post(() =>FileState.RenameState(oldPath, newPath));
         }*/
 
-        public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus)
+        public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus, string localFileMissingFromServer)
         {
             if (String.IsNullOrWhiteSpace(path))
                 throw new ArgumentNullException("path");
@@ -803,7 +816,7 @@ namespace Pithos.Core.Agents
                     
                     using (var connection = GetConnection())
                     {
-                        var command = new SQLiteCommand("delete from FileState where FilePath = :path or FilePath like :path + '/%'  COLLATE NOCASE",
+                        var command = new SQLiteCommand(@"delete from FileState where FilePath = :path or FilePath like :path || '\%'  COLLATE NOCASE",
                                                         connection);
 
                         command.Parameters.AddWithValue("path", filePath);
@@ -831,6 +844,65 @@ namespace Pithos.Core.Agents
             _persistenceAgent.Post(() => FileState.UpdateChecksum(path, shortHash,checksum));
         }
 
+
+        public void CleanupOrphanStates()
+        {
+            //Orphan states are those that do not correspond to an account, ie. their paths
+            //do not start with the root path of any registered account
+
+            var roots=(from account in Settings.Accounts
+                      select account.RootPath).ToList();
+            
+            var allStates = from state in FileState.Queryable
+                select state.FilePath;
+
+            foreach (var statePath in allStates)
+            {
+                if (!roots.Any(root=>statePath.StartsWith(root,StringComparison.InvariantCultureIgnoreCase)))
+                    this.DeleteDirect(statePath);
+            }
+        }
+
+        public void CleanupStaleStates(AccountInfo accountInfo, List<ObjectInfo> objectInfos)
+        {
+            if (accountInfo == null)
+                throw new ArgumentNullException("accountInfo");
+            if (objectInfos == null)
+                throw new ArgumentNullException("objectInfos");
+            Contract.EndContractBlock();
+            
+
+
+            //Stale states are those that have no corresponding local or server file
+            
+
+            var agent=FileAgent.GetFileAgent(accountInfo);
+
+            var localFiles=agent.EnumerateFiles();
+            var localSet = new HashSet<string>(localFiles);
+
+            //RelativeUrlToFilePath will fail for
+            //infos of accounts, containers which have no Name
+
+            var serverFiles = from info in objectInfos
+                              where info.Name != null
+                              select Path.Combine(accountInfo.AccountPath,info.RelativeUrlToFilePath(accountInfo.UserName));
+            var serverSet = new HashSet<string>(serverFiles);
+
+            var allStates = from state in FileState.Queryable
+                            where state.FilePath.StartsWith(agent.RootPath)
+                            select state.FilePath;
+            var stateSet = new HashSet<string>(allStates);
+            stateSet.ExceptWith(serverSet);
+            stateSet.ExceptWith(localSet);
+
+            foreach (var remainder in stateSet)
+            {
+                DeleteDirect(remainder);
+            }
+
+            
+        }
     }