Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / Agents / StatusAgent.cs @ d78d765c

History | View | Annotate | Download (34 kB)

1 255f5f86 Panagiotis Kanavos
#region
2 255f5f86 Panagiotis Kanavos
/* -----------------------------------------------------------------------
3 255f5f86 Panagiotis Kanavos
 * <copyright file="StatusAgent.cs" company="GRNet">
4 255f5f86 Panagiotis Kanavos
 * 
5 255f5f86 Panagiotis Kanavos
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
6 255f5f86 Panagiotis Kanavos
 *
7 255f5f86 Panagiotis Kanavos
 * Redistribution and use in source and binary forms, with or
8 255f5f86 Panagiotis Kanavos
 * without modification, are permitted provided that the following
9 255f5f86 Panagiotis Kanavos
 * conditions are met:
10 255f5f86 Panagiotis Kanavos
 *
11 255f5f86 Panagiotis Kanavos
 *   1. Redistributions of source code must retain the above
12 255f5f86 Panagiotis Kanavos
 *      copyright notice, this list of conditions and the following
13 255f5f86 Panagiotis Kanavos
 *      disclaimer.
14 255f5f86 Panagiotis Kanavos
 *
15 255f5f86 Panagiotis Kanavos
 *   2. Redistributions in binary form must reproduce the above
16 255f5f86 Panagiotis Kanavos
 *      copyright notice, this list of conditions and the following
17 255f5f86 Panagiotis Kanavos
 *      disclaimer in the documentation and/or other materials
18 255f5f86 Panagiotis Kanavos
 *      provided with the distribution.
19 255f5f86 Panagiotis Kanavos
 *
20 255f5f86 Panagiotis Kanavos
 *
21 255f5f86 Panagiotis Kanavos
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22 255f5f86 Panagiotis Kanavos
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 255f5f86 Panagiotis Kanavos
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 255f5f86 Panagiotis Kanavos
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25 255f5f86 Panagiotis Kanavos
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 255f5f86 Panagiotis Kanavos
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 255f5f86 Panagiotis Kanavos
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 255f5f86 Panagiotis Kanavos
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 255f5f86 Panagiotis Kanavos
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 255f5f86 Panagiotis Kanavos
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 255f5f86 Panagiotis Kanavos
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 255f5f86 Panagiotis Kanavos
 * POSSIBILITY OF SUCH DAMAGE.
33 255f5f86 Panagiotis Kanavos
 *
34 255f5f86 Panagiotis Kanavos
 * The views and conclusions contained in the software and
35 255f5f86 Panagiotis Kanavos
 * documentation are those of the authors and should not be
36 255f5f86 Panagiotis Kanavos
 * interpreted as representing official policies, either expressed
37 255f5f86 Panagiotis Kanavos
 * or implied, of GRNET S.A.
38 255f5f86 Panagiotis Kanavos
 * </copyright>
39 255f5f86 Panagiotis Kanavos
 * -----------------------------------------------------------------------
40 255f5f86 Panagiotis Kanavos
 */
41 255f5f86 Panagiotis Kanavos
#endregion
42 0eea575a Panagiotis Kanavos
using System;
43 0eea575a Panagiotis Kanavos
using System.Collections.Generic;
44 0eea575a Panagiotis Kanavos
using System.ComponentModel.Composition;
45 a0dcfcc9 Panagiotis Kanavos
using System.Data.SQLite;
46 0eea575a Panagiotis Kanavos
using System.Diagnostics;
47 0eea575a Panagiotis Kanavos
using System.Diagnostics.Contracts;
48 0eea575a Panagiotis Kanavos
using System.IO;
49 0eea575a Panagiotis Kanavos
using System.Linq;
50 db8a9589 Panagiotis Kanavos
using System.Reflection;
51 174bbb6e Panagiotis Kanavos
using System.Security.Cryptography;
52 540b8cf8 Panagiotis Kanavos
using System.Text;
53 0eea575a Panagiotis Kanavos
using System.Threading;
54 0eea575a Panagiotis Kanavos
using System.Threading.Tasks;
55 0eea575a Panagiotis Kanavos
using Castle.ActiveRecord;
56 174bbb6e Panagiotis Kanavos
using Castle.ActiveRecord.Framework;
57 0eea575a Panagiotis Kanavos
using Castle.ActiveRecord.Framework.Config;
58 6f03d6e1 Panagiotis Kanavos
using NHibernate.ByteCode.Castle;
59 6f03d6e1 Panagiotis Kanavos
using NHibernate.Cfg;
60 6f03d6e1 Panagiotis Kanavos
using NHibernate.Cfg.Loquacious;
61 6f03d6e1 Panagiotis Kanavos
using NHibernate.Dialect;
62 0eea575a Panagiotis Kanavos
using Pithos.Interfaces;
63 77e10b4f Panagiotis Kanavos
using Pithos.Network;
64 cfed7823 Panagiotis Kanavos
using log4net;
65 6f03d6e1 Panagiotis Kanavos
using Environment = System.Environment;
66 0eea575a Panagiotis Kanavos
67 cfed7823 Panagiotis Kanavos
namespace Pithos.Core.Agents
68 0eea575a Panagiotis Kanavos
{
69 0eea575a Panagiotis Kanavos
    [Export(typeof(IStatusChecker)),Export(typeof(IStatusKeeper))]
70 cfed7823 Panagiotis Kanavos
    public class StatusAgent:IStatusChecker,IStatusKeeper
71 0eea575a Panagiotis Kanavos
    {
72 db8a9589 Panagiotis Kanavos
        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
73 db8a9589 Panagiotis Kanavos
74 0eea575a Panagiotis Kanavos
        [System.ComponentModel.Composition.Import]
75 0eea575a Panagiotis Kanavos
        public IPithosSettings Settings { get; set; }
76 0eea575a Panagiotis Kanavos
77 4ec636f6 Panagiotis Kanavos
        private Agent<Action> _persistenceAgent;
78 0eea575a Panagiotis Kanavos
79 cfed7823 Panagiotis Kanavos
80 cfed7823 Panagiotis Kanavos
81 cfed7823 Panagiotis Kanavos
        public StatusAgent()
82 3c43ec9b Panagiotis Kanavos
        {            
83 3c43ec9b Panagiotis Kanavos
            var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
84 3c43ec9b Panagiotis Kanavos
85 adfa4645 Panagiotis Kanavos
            _pithosDataPath = Path.Combine(appDataPath , "GRNET\\PITHOS");
86 9c4346c9 Panagiotis Kanavos
            if (!Directory.Exists(_pithosDataPath))
87 9c4346c9 Panagiotis Kanavos
                Directory.CreateDirectory(_pithosDataPath);
88 618015f4 Panagiotis Kanavos
89 618015f4 Panagiotis Kanavos
            var dbPath = Path.Combine(_pithosDataPath, "pithos.db");
90 618015f4 Panagiotis Kanavos
91 618015f4 Panagiotis Kanavos
            MigrateOldDb(dbPath, appDataPath);
92 618015f4 Panagiotis Kanavos
93 6f03d6e1 Panagiotis Kanavos
94 9c4346c9 Panagiotis Kanavos
            var source = GetConfiguration(_pithosDataPath);
95 9c4346c9 Panagiotis Kanavos
            ActiveRecordStarter.Initialize(source,typeof(FileState),typeof(FileTag));
96 6f03d6e1 Panagiotis Kanavos
            
97 cfed7823 Panagiotis Kanavos
            ActiveRecordStarter.UpdateSchema();
98 9c4346c9 Panagiotis Kanavos
99 618015f4 Panagiotis Kanavos
100 618015f4 Panagiotis Kanavos
            if (!File.Exists(dbPath))
101 0eea575a Panagiotis Kanavos
                ActiveRecordStarter.CreateSchema();
102 9c4346c9 Panagiotis Kanavos
103 540b8cf8 Panagiotis Kanavos
            CreateTrigger();
104 025046f1 Panagiotis Kanavos
            
105 540b8cf8 Panagiotis Kanavos
        }
106 540b8cf8 Panagiotis Kanavos
107 618015f4 Panagiotis Kanavos
108 618015f4 Panagiotis Kanavos
        private static void MigrateOldDb(string dbPath, string appDataPath)
109 618015f4 Panagiotis Kanavos
        {
110 d78d765c pkanavos
            if(String.IsNullOrWhiteSpace(dbPath))
111 d78d765c pkanavos
                throw new ArgumentNullException("dbPath");
112 d78d765c pkanavos
            if(String.IsNullOrWhiteSpace(appDataPath))
113 d78d765c pkanavos
                throw new ArgumentNullException("appDataPath");
114 d78d765c pkanavos
            Contract.EndContractBlock();
115 81c5c310 pkanavos
116 618015f4 Panagiotis Kanavos
            var oldDbPath = Path.Combine(appDataPath, "Pithos", "pithos.db");
117 618015f4 Panagiotis Kanavos
            var oldDbInfo = new FileInfo(oldDbPath);
118 618015f4 Panagiotis Kanavos
            if (oldDbInfo.Exists && !File.Exists(dbPath))
119 618015f4 Panagiotis Kanavos
            {
120 81c5c310 pkanavos
                Log.InfoFormat("Moving database from {0} to {1}",oldDbInfo.FullName,dbPath);
121 618015f4 Panagiotis Kanavos
                var oldDirectory = oldDbInfo.Directory;
122 81c5c310 pkanavos
                oldDbInfo.MoveTo(dbPath);
123 81c5c310 pkanavos
                
124 81c5c310 pkanavos
                if (Log.IsDebugEnabled)
125 81c5c310 pkanavos
                    Log.DebugFormat("Deleting {0}",oldDirectory.FullName);
126 81c5c310 pkanavos
                
127 618015f4 Panagiotis Kanavos
                oldDirectory.Delete(true);
128 618015f4 Panagiotis Kanavos
            }
129 618015f4 Panagiotis Kanavos
        }
130 618015f4 Panagiotis Kanavos
131 540b8cf8 Panagiotis Kanavos
        private void CreateTrigger()
132 540b8cf8 Panagiotis Kanavos
        {
133 540b8cf8 Panagiotis Kanavos
            using (var connection = GetConnection())
134 540b8cf8 Panagiotis Kanavos
            using (var triggerCommand = connection.CreateCommand())
135 540b8cf8 Panagiotis Kanavos
            {
136 540b8cf8 Panagiotis Kanavos
                var cmdText = new StringBuilder()
137 540b8cf8 Panagiotis Kanavos
                    .AppendLine("CREATE TRIGGER IF NOT EXISTS update_last_modified UPDATE ON FileState FOR EACH ROW")
138 540b8cf8 Panagiotis Kanavos
                    .AppendLine("BEGIN")
139 540b8cf8 Panagiotis Kanavos
                    .AppendLine("UPDATE FileState SET Modified=datetime('now')  WHERE Id=old.Id;")
140 540b8cf8 Panagiotis Kanavos
                    .AppendLine("END;")
141 540b8cf8 Panagiotis Kanavos
                    .AppendLine("CREATE TRIGGER IF NOT EXISTS insert_last_modified INSERT ON FileState FOR EACH ROW")
142 540b8cf8 Panagiotis Kanavos
                    .AppendLine("BEGIN")
143 540b8cf8 Panagiotis Kanavos
                    .AppendLine("UPDATE FileState SET Modified=datetime('now')  WHERE Id=new.Id;")
144 540b8cf8 Panagiotis Kanavos
                    .AppendLine("END;")
145 540b8cf8 Panagiotis Kanavos
                    .ToString();
146 540b8cf8 Panagiotis Kanavos
                triggerCommand.CommandText = cmdText;                
147 540b8cf8 Panagiotis Kanavos
                triggerCommand.ExecuteNonQuery();
148 540b8cf8 Panagiotis Kanavos
            }
149 540b8cf8 Panagiotis Kanavos
        }
150 039a89e5 Panagiotis Kanavos
151 039a89e5 Panagiotis Kanavos
152 3c43ec9b Panagiotis Kanavos
        private static InPlaceConfigurationSource GetConfiguration(string pithosDbPath)
153 3c43ec9b Panagiotis Kanavos
        {
154 9c4346c9 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(pithosDbPath))
155 9c4346c9 Panagiotis Kanavos
                throw new ArgumentNullException("pithosDbPath");
156 9c4346c9 Panagiotis Kanavos
            if (!Path.IsPathRooted(pithosDbPath))
157 9c4346c9 Panagiotis Kanavos
                throw new ArgumentException("path must be a rooted path", "pithosDbPath");
158 9c4346c9 Panagiotis Kanavos
            Contract.EndContractBlock();
159 9c4346c9 Panagiotis Kanavos
160 3c43ec9b Panagiotis Kanavos
            var properties = new Dictionary<string, string>
161 3c43ec9b Panagiotis Kanavos
                                 {
162 3c43ec9b Panagiotis Kanavos
                                     {"connection.driver_class", "NHibernate.Driver.SQLite20Driver"},
163 3c43ec9b Panagiotis Kanavos
                                     {"dialect", "NHibernate.Dialect.SQLiteDialect"},
164 3c43ec9b Panagiotis Kanavos
                                     {"connection.provider", "NHibernate.Connection.DriverConnectionProvider"},
165 3c43ec9b Panagiotis Kanavos
                                     {
166 3c43ec9b Panagiotis Kanavos
                                         "proxyfactory.factory_class",
167 3c43ec9b Panagiotis Kanavos
                                         "NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle"
168 3c43ec9b Panagiotis Kanavos
                                         },
169 3c43ec9b Panagiotis Kanavos
                                 };
170 3c43ec9b Panagiotis Kanavos
171 e81dd1f6 Panagiotis Kanavos
            var connectionString = String.Format(@"Data Source={0}\pithos.db;Version=3;Enlist=N", pithosDbPath);
172 3c43ec9b Panagiotis Kanavos
            properties.Add("connection.connection_string", connectionString);
173 3c43ec9b Panagiotis Kanavos
174 5120f3cb Panagiotis Kanavos
            var source = new InPlaceConfigurationSource();                        
175 3c43ec9b Panagiotis Kanavos
            source.Add(typeof (ActiveRecordBase), properties);
176 5120f3cb Panagiotis Kanavos
            source.SetDebugFlag(false);            
177 3c43ec9b Panagiotis Kanavos
            return source;
178 3c43ec9b Panagiotis Kanavos
        }
179 3c43ec9b Panagiotis Kanavos
180 3c43ec9b Panagiotis Kanavos
        public void StartProcessing(CancellationToken token)
181 3c43ec9b Panagiotis Kanavos
        {
182 4ec636f6 Panagiotis Kanavos
            _persistenceAgent = Agent<Action>.Start(queue =>
183 9c4346c9 Panagiotis Kanavos
            {
184 4ec636f6 Panagiotis Kanavos
                Action loop = null;
185 4ec636f6 Panagiotis Kanavos
                loop = () =>
186 4ec636f6 Panagiotis Kanavos
                {
187 4ec636f6 Panagiotis Kanavos
                    var job = queue.Receive();
188 4ec636f6 Panagiotis Kanavos
                    job.ContinueWith(t =>
189 5e31048f Panagiotis Kanavos
                    {
190 4ec636f6 Panagiotis Kanavos
                        var action = job.Result;
191 4ec636f6 Panagiotis Kanavos
                        try
192 4ec636f6 Panagiotis Kanavos
                        {
193 4ec636f6 Panagiotis Kanavos
                            action();
194 4ec636f6 Panagiotis Kanavos
                        }
195 a0dcfcc9 Panagiotis Kanavos
                        catch (SQLiteException ex)
196 a0dcfcc9 Panagiotis Kanavos
                        {
197 a0dcfcc9 Panagiotis Kanavos
                            Log.ErrorFormat("[ERROR] SQL \n{0}", ex);
198 a0dcfcc9 Panagiotis Kanavos
                        }
199 4ec636f6 Panagiotis Kanavos
                        catch (Exception ex)
200 4ec636f6 Panagiotis Kanavos
                        {
201 a0dcfcc9 Panagiotis Kanavos
                            Log.ErrorFormat("[ERROR] STATE \n{0}", ex);
202 4ec636f6 Panagiotis Kanavos
                        }
203 174bbb6e Panagiotis Kanavos
                        queue.NotifyComplete(action);
204 a0dcfcc9 Panagiotis Kanavos
// ReSharper disable AccessToModifiedClosure
205 4ec636f6 Panagiotis Kanavos
                        queue.DoAsync(loop);
206 a0dcfcc9 Panagiotis Kanavos
// ReSharper restore AccessToModifiedClosure
207 4ec636f6 Panagiotis Kanavos
                    });
208 4ec636f6 Panagiotis Kanavos
                };
209 4ec636f6 Panagiotis Kanavos
                loop();
210 9c4346c9 Panagiotis Kanavos
            });
211 d15e99b4 Panagiotis Kanavos
            
212 0eea575a Panagiotis Kanavos
        }
213 0eea575a Panagiotis Kanavos
214 d15e99b4 Panagiotis Kanavos
       
215 0eea575a Panagiotis Kanavos
216 0eea575a Panagiotis Kanavos
        public void Stop()
217 0eea575a Panagiotis Kanavos
        {
218 4ec636f6 Panagiotis Kanavos
            _persistenceAgent.Stop();            
219 0eea575a Panagiotis Kanavos
        }
220 174bbb6e Panagiotis Kanavos
               
221 0eea575a Panagiotis Kanavos
222 0af3141d Panagiotis Kanavos
        public void ProcessExistingFiles(IEnumerable<FileInfo> existingFiles)
223 9c4346c9 Panagiotis Kanavos
        {
224 0af3141d Panagiotis Kanavos
            if(existingFiles  ==null)
225 0af3141d Panagiotis Kanavos
                throw new ArgumentNullException("existingFiles");
226 0af3141d Panagiotis Kanavos
            Contract.EndContractBlock();
227 9c4346c9 Panagiotis Kanavos
            
228 0af3141d Panagiotis Kanavos
            //Find new or matching files with a left join to the stored states
229 0af3141d Panagiotis Kanavos
            var fileStates = FileState.Queryable;
230 0af3141d Panagiotis Kanavos
            var currentFiles=from file in existingFiles
231 0af3141d Panagiotis Kanavos
                      join state in fileStates on file.FullName.ToLower() equals state.FilePath.ToLower() into gs
232 0af3141d Panagiotis Kanavos
                      from substate in gs.DefaultIfEmpty()
233 0af3141d Panagiotis Kanavos
                               select new {File = file, State = substate};
234 0af3141d Panagiotis Kanavos
235 0af3141d Panagiotis Kanavos
            //To get the deleted files we must get the states that have no corresponding
236 0af3141d Panagiotis Kanavos
            //files. 
237 0af3141d Panagiotis Kanavos
            //We can't use the File.Exists method inside a query, so we get all file paths from the states
238 0af3141d Panagiotis Kanavos
            var statePaths = (from state in fileStates
239 0af3141d Panagiotis Kanavos
                             select new {state.Id, state.FilePath}).ToList();
240 0af3141d Panagiotis Kanavos
            //and check each one
241 0af3141d Panagiotis Kanavos
            var missingStates= (from path in statePaths
242 4ec636f6 Panagiotis Kanavos
                                where !File.Exists(path.FilePath) && !Directory.Exists(path.FilePath)
243 0af3141d Panagiotis Kanavos
                               select path.Id).ToList();
244 0af3141d Panagiotis Kanavos
            //Finally, retrieve the states that correspond to the deleted files            
245 0af3141d Panagiotis Kanavos
            var deletedFiles = from state in fileStates 
246 0af3141d Panagiotis Kanavos
                        where missingStates.Contains(state.Id)
247 0af3141d Panagiotis Kanavos
                        select new { File = default(FileInfo), State = state };
248 0af3141d Panagiotis Kanavos
249 174bbb6e Panagiotis Kanavos
            var pairs = currentFiles.Union(deletedFiles).ToList();
250 0af3141d Panagiotis Kanavos
251 174bbb6e Panagiotis Kanavos
            using (var shortHasher = HashAlgorithm.Create("sha1"))
252 0eea575a Panagiotis Kanavos
            {
253 174bbb6e Panagiotis Kanavos
                foreach (var pair in pairs)
254 0af3141d Panagiotis Kanavos
                {
255 174bbb6e Panagiotis Kanavos
                    var fileState = pair.State;
256 174bbb6e Panagiotis Kanavos
                    var file = pair.File;
257 174bbb6e Panagiotis Kanavos
                    if (fileState == null)
258 9c4346c9 Panagiotis Kanavos
                    {
259 174bbb6e Panagiotis Kanavos
                        //This is a new file                        
260 174bbb6e Panagiotis Kanavos
                        var createState = FileState.CreateFor(file);
261 174bbb6e Panagiotis Kanavos
                        _persistenceAgent.Post(createState.Create);                        
262 174bbb6e Panagiotis Kanavos
                    }
263 174bbb6e Panagiotis Kanavos
                    else if (file == null)
264 174bbb6e Panagiotis Kanavos
                    {
265 174bbb6e Panagiotis Kanavos
                        //This file was deleted while we were down. We should mark it as deleted
266 174bbb6e Panagiotis Kanavos
                        //We have to go through UpdateStatus here because the state object we are using
267 174bbb6e Panagiotis Kanavos
                        //was created by a different ORM session.
268 174bbb6e Panagiotis Kanavos
                        _persistenceAgent.Post(() => UpdateStatusDirect(fileState.Id, FileStatus.Deleted));
269 174bbb6e Panagiotis Kanavos
                    }
270 174bbb6e Panagiotis Kanavos
                    else
271 174bbb6e Panagiotis Kanavos
                    {
272 174bbb6e Panagiotis Kanavos
                        //This file has a matching state. Need to check for possible changes
273 174bbb6e Panagiotis Kanavos
                        //To check for changes, we use the cheap (in CPU terms) SHA1 algorithm
274 174bbb6e Panagiotis Kanavos
                        //on the entire file.
275 174bbb6e Panagiotis Kanavos
                        
276 174bbb6e Panagiotis Kanavos
                        var hashString = file.ComputeShortHash(shortHasher);                        
277 174bbb6e Panagiotis Kanavos
                        //TODO: Need a way to attach the hashes to the filestate so we don't
278 174bbb6e Panagiotis Kanavos
                        //recalculate them each time a call to calculate has is made
279 174bbb6e Panagiotis Kanavos
                        //We can either store them to the filestate or add them to a 
280 174bbb6e Panagiotis Kanavos
                        //dictionary
281 174bbb6e Panagiotis Kanavos
282 174bbb6e Panagiotis Kanavos
                        //If the hashes don't match the file was changed
283 174bbb6e Panagiotis Kanavos
                        if (fileState.ShortHash != hashString)
284 174bbb6e Panagiotis Kanavos
                        {
285 174bbb6e Panagiotis Kanavos
                            _persistenceAgent.Post(() => UpdateStatusDirect(fileState.Id, FileStatus.Modified));
286 174bbb6e Panagiotis Kanavos
                        }
287 174bbb6e Panagiotis Kanavos
                    }
288 0af3141d Panagiotis Kanavos
                }
289 174bbb6e Panagiotis Kanavos
            }
290 174bbb6e Panagiotis Kanavos
                        
291 0af3141d Panagiotis Kanavos
         
292 0eea575a Panagiotis Kanavos
        }
293 174bbb6e Panagiotis Kanavos
        
294 174bbb6e Panagiotis Kanavos
295 0eea575a Panagiotis Kanavos
296 e81dd1f6 Panagiotis Kanavos
        private int UpdateStatusDirect(Guid id, FileStatus status)
297 e81dd1f6 Panagiotis Kanavos
        {
298 039a89e5 Panagiotis Kanavos
            using (log4net.ThreadContext.Stacks["StatusAgent"].Push("UpdateStatusDirect"))
299 e81dd1f6 Panagiotis Kanavos
            {
300 e81dd1f6 Panagiotis Kanavos
301 039a89e5 Panagiotis Kanavos
                try
302 e81dd1f6 Panagiotis Kanavos
                {
303 1b4a7550 Panagiotis Kanavos
                    
304 039a89e5 Panagiotis Kanavos
                    using (var connection = GetConnection())
305 039a89e5 Panagiotis Kanavos
                    using (
306 039a89e5 Panagiotis Kanavos
                        var command = new SQLiteCommand("update FileState set FileStatus= :fileStatus where Id = :id  ",
307 039a89e5 Panagiotis Kanavos
                                                        connection))
308 039a89e5 Panagiotis Kanavos
                    {                                                
309 039a89e5 Panagiotis Kanavos
                        command.Parameters.AddWithValue("fileStatus", status);
310 039a89e5 Panagiotis Kanavos
311 039a89e5 Panagiotis Kanavos
                        command.Parameters.AddWithValue("id", id);
312 039a89e5 Panagiotis Kanavos
                        
313 039a89e5 Panagiotis Kanavos
                        var affected = command.ExecuteNonQuery();
314 039a89e5 Panagiotis Kanavos
                        
315 039a89e5 Panagiotis Kanavos
                        return affected;
316 039a89e5 Panagiotis Kanavos
                    }
317 e81dd1f6 Panagiotis Kanavos
318 039a89e5 Panagiotis Kanavos
                }
319 039a89e5 Panagiotis Kanavos
                catch (Exception exc)
320 039a89e5 Panagiotis Kanavos
                {
321 039a89e5 Panagiotis Kanavos
                    Log.Error(exc.ToString());
322 039a89e5 Panagiotis Kanavos
                    throw;
323 e81dd1f6 Panagiotis Kanavos
                }
324 e81dd1f6 Panagiotis Kanavos
            }
325 e81dd1f6 Panagiotis Kanavos
        }
326 e81dd1f6 Panagiotis Kanavos
        
327 e81dd1f6 Panagiotis Kanavos
        private int UpdateStatusDirect(string path, FileStatus status)
328 e81dd1f6 Panagiotis Kanavos
        {
329 039a89e5 Panagiotis Kanavos
            using (log4net.ThreadContext.Stacks["StatusAgent"].Push("UpdateStatusDirect"))
330 e81dd1f6 Panagiotis Kanavos
            {
331 e81dd1f6 Panagiotis Kanavos
332 039a89e5 Panagiotis Kanavos
                try
333 e81dd1f6 Panagiotis Kanavos
                {
334 039a89e5 Panagiotis Kanavos
335 1b4a7550 Panagiotis Kanavos
                    
336 039a89e5 Panagiotis Kanavos
                    using (var connection = GetConnection())
337 039a89e5 Panagiotis Kanavos
                    using (
338 039a89e5 Panagiotis Kanavos
                        var command =
339 3c76f045 Panagiotis Kanavos
                            new SQLiteCommand("update FileState set FileStatus= :fileStatus where FilePath = :path COLLATE NOCASE",
340 039a89e5 Panagiotis Kanavos
                                              connection))
341 039a89e5 Panagiotis Kanavos
                    {
342 e81dd1f6 Panagiotis Kanavos
343 e81dd1f6 Panagiotis Kanavos
344 039a89e5 Panagiotis Kanavos
                        command.Parameters.AddWithValue("fileStatus", status);
345 039a89e5 Panagiotis Kanavos
346 3c76f045 Panagiotis Kanavos
                        command.Parameters.AddWithValue("path", path);
347 039a89e5 Panagiotis Kanavos
                        
348 039a89e5 Panagiotis Kanavos
                        var affected = command.ExecuteNonQuery();
349 039a89e5 Panagiotis Kanavos
                        return affected;
350 039a89e5 Panagiotis Kanavos
                    }
351 039a89e5 Panagiotis Kanavos
                }
352 039a89e5 Panagiotis Kanavos
                catch (Exception exc)
353 039a89e5 Panagiotis Kanavos
                {
354 039a89e5 Panagiotis Kanavos
                    Log.Error(exc.ToString());
355 039a89e5 Panagiotis Kanavos
                    throw;
356 e81dd1f6 Panagiotis Kanavos
                }
357 e81dd1f6 Panagiotis Kanavos
            }
358 e81dd1f6 Panagiotis Kanavos
        }
359 e81dd1f6 Panagiotis Kanavos
360 e81dd1f6 Panagiotis Kanavos
        private int UpdateStatusDirect(string absolutePath, FileStatus fileStatus, FileOverlayStatus overlayStatus)
361 e81dd1f6 Panagiotis Kanavos
        {
362 039a89e5 Panagiotis Kanavos
            using (log4net.ThreadContext.Stacks["StatusAgent"].Push("UpdateStatusDirect"))
363 e81dd1f6 Panagiotis Kanavos
            {
364 e81dd1f6 Panagiotis Kanavos
365 039a89e5 Panagiotis Kanavos
                try
366 e81dd1f6 Panagiotis Kanavos
                {
367 039a89e5 Panagiotis Kanavos
368 1b4a7550 Panagiotis Kanavos
                    
369 039a89e5 Panagiotis Kanavos
                    using (var connection = GetConnection())
370 039a89e5 Panagiotis Kanavos
                    using (
371 039a89e5 Panagiotis Kanavos
                        var command =
372 039a89e5 Panagiotis Kanavos
                            new SQLiteCommand(
373 3c76f045 Panagiotis Kanavos
                                "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path COLLATE NOCASE ",
374 039a89e5 Panagiotis Kanavos
                                connection))
375 039a89e5 Panagiotis Kanavos
                    {
376 039a89e5 Panagiotis Kanavos
377 3c76f045 Panagiotis Kanavos
                        command.Parameters.AddWithValue("path", absolutePath);
378 039a89e5 Panagiotis Kanavos
                        command.Parameters.AddWithValue("fileStatus", fileStatus);
379 039a89e5 Panagiotis Kanavos
                        command.Parameters.AddWithValue("overlayStatus", overlayStatus);
380 039a89e5 Panagiotis Kanavos
                        
381 039a89e5 Panagiotis Kanavos
                        var affected = command.ExecuteNonQuery();
382 039a89e5 Panagiotis Kanavos
                        return affected;
383 039a89e5 Panagiotis Kanavos
                    }
384 039a89e5 Panagiotis Kanavos
                }
385 039a89e5 Panagiotis Kanavos
                catch (Exception exc)
386 039a89e5 Panagiotis Kanavos
                {
387 039a89e5 Panagiotis Kanavos
                    Log.Error(exc.ToString());
388 039a89e5 Panagiotis Kanavos
                    throw;
389 e81dd1f6 Panagiotis Kanavos
                }
390 e81dd1f6 Panagiotis Kanavos
            }
391 e81dd1f6 Panagiotis Kanavos
        }
392 e81dd1f6 Panagiotis Kanavos
        
393 0af3141d Panagiotis Kanavos
394 0eea575a Panagiotis Kanavos
395 9c4346c9 Panagiotis Kanavos
        public string BlockHash { get; set; }
396 9c4346c9 Panagiotis Kanavos
397 9c4346c9 Panagiotis Kanavos
        public int BlockSize { get; set; }
398 5120f3cb Panagiotis Kanavos
        public void ChangeRoots(string oldPath, string newPath)
399 5120f3cb Panagiotis Kanavos
        {
400 5120f3cb Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(oldPath))
401 5120f3cb Panagiotis Kanavos
                throw new ArgumentNullException("oldPath");
402 5120f3cb Panagiotis Kanavos
            if (!Path.IsPathRooted(oldPath))
403 5120f3cb Panagiotis Kanavos
                throw new ArgumentException("oldPath must be an absolute path", "oldPath");
404 5120f3cb Panagiotis Kanavos
            if (string.IsNullOrWhiteSpace(newPath))
405 5120f3cb Panagiotis Kanavos
                throw new ArgumentNullException("newPath");
406 5120f3cb Panagiotis Kanavos
            if (!Path.IsPathRooted(newPath))
407 5120f3cb Panagiotis Kanavos
                throw new ArgumentException("newPath must be an absolute path", "newPath");
408 5120f3cb Panagiotis Kanavos
            Contract.EndContractBlock();
409 5120f3cb Panagiotis Kanavos
410 5120f3cb Panagiotis Kanavos
            FileState.ChangeRootPath(oldPath,newPath);
411 5120f3cb Panagiotis Kanavos
412 5120f3cb Panagiotis Kanavos
        }
413 9c4346c9 Panagiotis Kanavos
414 0eea575a Panagiotis Kanavos
415 283809f3 Panagiotis Kanavos
416 a0dcfcc9 Panagiotis Kanavos
        private readonly string _pithosDataPath;
417 283809f3 Panagiotis Kanavos
418 283809f3 Panagiotis Kanavos
419 039a89e5 Panagiotis Kanavos
        public FileState GetStateByFilePath(string path)
420 039a89e5 Panagiotis Kanavos
        {
421 039a89e5 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
422 039a89e5 Panagiotis Kanavos
                throw new ArgumentNullException("path");
423 039a89e5 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
424 039a89e5 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");
425 039a89e5 Panagiotis Kanavos
            Contract.EndContractBlock();
426 039a89e5 Panagiotis Kanavos
427 039a89e5 Panagiotis Kanavos
            try
428 039a89e5 Panagiotis Kanavos
            {
429 039a89e5 Panagiotis Kanavos
                
430 039a89e5 Panagiotis Kanavos
                using (var connection = GetConnection())
431 174bbb6e Panagiotis Kanavos
                using (var command = new SQLiteCommand("select Id, FilePath, OverlayStatus,FileStatus ,Checksum ,ShortHash,Version    ,VersionTimeStamp,IsShared   ,SharedBy   ,ShareWrite  from FileState where FilePath=:path COLLATE NOCASE", connection))
432 039a89e5 Panagiotis Kanavos
                {
433 039a89e5 Panagiotis Kanavos
                    
434 3c76f045 Panagiotis Kanavos
                    command.Parameters.AddWithValue("path", path);
435 039a89e5 Panagiotis Kanavos
                    
436 039a89e5 Panagiotis Kanavos
                    using (var reader = command.ExecuteReader())
437 039a89e5 Panagiotis Kanavos
                    {
438 039a89e5 Panagiotis Kanavos
                        if (reader.Read())
439 039a89e5 Panagiotis Kanavos
                        {
440 039a89e5 Panagiotis Kanavos
                            //var values = new object[reader.FieldCount];
441 039a89e5 Panagiotis Kanavos
                            //reader.GetValues(values);
442 039a89e5 Panagiotis Kanavos
                            var state = new FileState
443 039a89e5 Panagiotis Kanavos
                                            {
444 039a89e5 Panagiotis Kanavos
                                                Id = reader.GetGuid(0),
445 039a89e5 Panagiotis Kanavos
                                                FilePath = reader.IsDBNull(1)?"":reader.GetString(1),
446 039a89e5 Panagiotis Kanavos
                                                OverlayStatus =reader.IsDBNull(2)?FileOverlayStatus.Unversioned: (FileOverlayStatus) reader.GetInt64(2),
447 039a89e5 Panagiotis Kanavos
                                                FileStatus = reader.IsDBNull(3)?FileStatus.Missing:(FileStatus) reader.GetInt64(3),
448 039a89e5 Panagiotis Kanavos
                                                Checksum = reader.IsDBNull(4)?"":reader.GetString(4),
449 174bbb6e Panagiotis Kanavos
                                                ShortHash= reader.IsDBNull(5)?"":reader.GetString(5),
450 174bbb6e Panagiotis Kanavos
                                                Version = reader.IsDBNull(6)?default(long):reader.GetInt64(6),
451 174bbb6e Panagiotis Kanavos
                                                VersionTimeStamp = reader.IsDBNull(7)?default(DateTime):reader.GetDateTime(7),
452 174bbb6e Panagiotis Kanavos
                                                IsShared = !reader.IsDBNull(8) && reader.GetBoolean(8),
453 174bbb6e Panagiotis Kanavos
                                                SharedBy = reader.IsDBNull(9)?"":reader.GetString(9),
454 174bbb6e Panagiotis Kanavos
                                                ShareWrite = !reader.IsDBNull(10) && reader.GetBoolean(10)
455 039a89e5 Panagiotis Kanavos
                                            };
456 039a89e5 Panagiotis Kanavos
/*
457 039a89e5 Panagiotis Kanavos
                            var state = new FileState
458 039a89e5 Panagiotis Kanavos
                                            {
459 039a89e5 Panagiotis Kanavos
                                                Id = (Guid) values[0],
460 039a89e5 Panagiotis Kanavos
                                                FilePath = (string) values[1],
461 039a89e5 Panagiotis Kanavos
                                                OverlayStatus = (FileOverlayStatus) (long)values[2],
462 039a89e5 Panagiotis Kanavos
                                                FileStatus = (FileStatus) (long)values[3],
463 039a89e5 Panagiotis Kanavos
                                                Checksum = (string) values[4],
464 039a89e5 Panagiotis Kanavos
                                                Version = (long?) values[5],
465 039a89e5 Panagiotis Kanavos
                                                VersionTimeStamp = (DateTime?) values[6],
466 039a89e5 Panagiotis Kanavos
                                                IsShared = (long)values[7] == 1,
467 039a89e5 Panagiotis Kanavos
                                                SharedBy = (string) values[8],
468 039a89e5 Panagiotis Kanavos
                                                ShareWrite = (long)values[9] == 1
469 039a89e5 Panagiotis Kanavos
                                            };
470 039a89e5 Panagiotis Kanavos
*/
471 039a89e5 Panagiotis Kanavos
                            return state;
472 039a89e5 Panagiotis Kanavos
                        }
473 039a89e5 Panagiotis Kanavos
                        else
474 039a89e5 Panagiotis Kanavos
                        {
475 039a89e5 Panagiotis Kanavos
                            return null;
476 039a89e5 Panagiotis Kanavos
                        }
477 039a89e5 Panagiotis Kanavos
478 039a89e5 Panagiotis Kanavos
                    }                    
479 039a89e5 Panagiotis Kanavos
                }
480 039a89e5 Panagiotis Kanavos
            }
481 039a89e5 Panagiotis Kanavos
            catch (Exception exc)
482 039a89e5 Panagiotis Kanavos
            {
483 039a89e5 Panagiotis Kanavos
                Log.ErrorFormat(exc.ToString());
484 039a89e5 Panagiotis Kanavos
                throw;
485 039a89e5 Panagiotis Kanavos
            }            
486 039a89e5 Panagiotis Kanavos
        }
487 039a89e5 Panagiotis Kanavos
488 283809f3 Panagiotis Kanavos
        public FileOverlayStatus GetFileOverlayStatus(string path)
489 283809f3 Panagiotis Kanavos
        {
490 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
491 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("path");
492 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
493 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");
494 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
495 cfed7823 Panagiotis Kanavos
496 283809f3 Panagiotis Kanavos
            try
497 283809f3 Panagiotis Kanavos
            {
498 039a89e5 Panagiotis Kanavos
                
499 039a89e5 Panagiotis Kanavos
                using (var connection = GetConnection())
500 3c76f045 Panagiotis Kanavos
                using (var command = new SQLiteCommand("select OverlayStatus from FileState where FilePath=:path  COLLATE NOCASE", connection))
501 e81dd1f6 Panagiotis Kanavos
                {
502 1b4a7550 Panagiotis Kanavos
                    
503 3c76f045 Panagiotis Kanavos
                    command.Parameters.AddWithValue("path", path);
504 039a89e5 Panagiotis Kanavos
                    
505 e81dd1f6 Panagiotis Kanavos
                    var s = command.ExecuteScalar();
506 e81dd1f6 Panagiotis Kanavos
                    return (FileOverlayStatus) Convert.ToInt32(s);
507 e81dd1f6 Panagiotis Kanavos
                }
508 283809f3 Panagiotis Kanavos
            }
509 283809f3 Panagiotis Kanavos
            catch (Exception exc)
510 283809f3 Panagiotis Kanavos
            {
511 5120f3cb Panagiotis Kanavos
                Log.ErrorFormat(exc.ToString());
512 283809f3 Panagiotis Kanavos
                return FileOverlayStatus.Unversioned;
513 283809f3 Panagiotis Kanavos
            }
514 283809f3 Panagiotis Kanavos
        }
515 283809f3 Panagiotis Kanavos
516 e81dd1f6 Panagiotis Kanavos
        private string GetConnectionString()
517 e81dd1f6 Panagiotis Kanavos
        {
518 14ecd267 Panagiotis Kanavos
            var connectionString = String.Format(@"Data Source={0}\pithos.db;Version=3;Enlist=N;Pooling=True", _pithosDataPath);
519 e81dd1f6 Panagiotis Kanavos
            return connectionString;
520 e81dd1f6 Panagiotis Kanavos
        }
521 e81dd1f6 Panagiotis Kanavos
522 039a89e5 Panagiotis Kanavos
        private SQLiteConnection GetConnection()
523 039a89e5 Panagiotis Kanavos
        {
524 039a89e5 Panagiotis Kanavos
            var connectionString = GetConnectionString();
525 039a89e5 Panagiotis Kanavos
            var connection = new SQLiteConnection(connectionString);
526 039a89e5 Panagiotis Kanavos
            connection.Open();
527 039a89e5 Panagiotis Kanavos
            using(var cmd =connection.CreateCommand())
528 039a89e5 Panagiotis Kanavos
            {
529 039a89e5 Panagiotis Kanavos
                cmd.CommandText = "PRAGMA journal_mode=WAL";
530 039a89e5 Panagiotis Kanavos
                cmd.ExecuteNonQuery();
531 039a89e5 Panagiotis Kanavos
            }
532 039a89e5 Panagiotis Kanavos
            return connection;
533 039a89e5 Panagiotis Kanavos
        }
534 039a89e5 Panagiotis Kanavos
535 174bbb6e Panagiotis Kanavos
       /* public void SetFileOverlayStatus(string path, FileOverlayStatus overlayStatus)
536 0eea575a Panagiotis Kanavos
        {
537 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
538 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("path");
539 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
540 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted","path");
541 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
542 cfed7823 Panagiotis Kanavos
543 3c76f045 Panagiotis Kanavos
            _persistenceAgent.Post(() => FileState.StoreOverlayStatus(path,overlayStatus));
544 174bbb6e Panagiotis Kanavos
        }*/
545 174bbb6e Panagiotis Kanavos
546 174bbb6e Panagiotis Kanavos
        public Task SetFileOverlayStatus(string path, FileOverlayStatus overlayStatus, string shortHash = null)
547 174bbb6e Panagiotis Kanavos
        {
548 174bbb6e Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
549 174bbb6e Panagiotis Kanavos
                throw new ArgumentNullException("path");
550 174bbb6e Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
551 174bbb6e Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted","path");
552 174bbb6e Panagiotis Kanavos
            Contract.EndContractBlock();
553 174bbb6e Panagiotis Kanavos
554 174bbb6e Panagiotis Kanavos
            return _persistenceAgent.PostAndAwait(() => FileState.StoreOverlayStatus(path,overlayStatus,shortHash));
555 0eea575a Panagiotis Kanavos
        }
556 0eea575a Panagiotis Kanavos
557 a0dcfcc9 Panagiotis Kanavos
       /* public void RenameFileOverlayStatus(string oldPath, string newPath)
558 bfc13ed8 Panagiotis Kanavos
        {
559 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(oldPath))
560 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("oldPath");
561 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(oldPath))
562 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The oldPath must be rooted", "oldPath");
563 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(newPath))
564 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("newPath");
565 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(newPath))
566 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The newPath must be rooted", "newPath");
567 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
568 cfed7823 Panagiotis Kanavos
569 ab2f6f79 Panagiotis Kanavos
            _persistenceAgent.Post(() =>FileState.RenameState(oldPath, newPath));
570 a0dcfcc9 Panagiotis Kanavos
        }*/
571 0eea575a Panagiotis Kanavos
572 283809f3 Panagiotis Kanavos
        public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus)
573 0eea575a Panagiotis Kanavos
        {
574 283809f3 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
575 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("path");
576 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
577 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");
578 bfc13ed8 Panagiotis Kanavos
            Contract.EndContractBlock();
579 bfc13ed8 Panagiotis Kanavos
580 ab2f6f79 Panagiotis Kanavos
            Debug.Assert(!path.Contains(FolderConstants.CacheFolder));
581 ab2f6f79 Panagiotis Kanavos
            Debug.Assert(!path.EndsWith(".ignore"));
582 4ec636f6 Panagiotis Kanavos
583 3c76f045 Panagiotis Kanavos
            _persistenceAgent.Post(() => UpdateStatusDirect(path, fileStatus, overlayStatus));
584 0eea575a Panagiotis Kanavos
        }
585 0eea575a Panagiotis Kanavos
586 039a89e5 Panagiotis Kanavos
/*
587 283809f3 Panagiotis Kanavos
        public void StoreInfo(string path,ObjectInfo objectInfo)
588 0eea575a Panagiotis Kanavos
        {
589 283809f3 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
590 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("path");
591 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
592 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");            
593 cfed7823 Panagiotis Kanavos
            if (objectInfo == null)
594 283809f3 Panagiotis Kanavos
                throw new ArgumentNullException("objectInfo", "objectInfo can't be empty");
595 bfc13ed8 Panagiotis Kanavos
            Contract.EndContractBlock();
596 5ce54458 Panagiotis Kanavos
597 5ce54458 Panagiotis Kanavos
            _persistenceAgent.Post(() =>
598 3c43ec9b Panagiotis Kanavos
            {
599 5ce54458 Panagiotis Kanavos
                var filePath = path.ToLower();
600 5ce54458 Panagiotis Kanavos
                //Load the existing files state and set its properties in one session            
601 5ce54458 Panagiotis Kanavos
                using (new SessionScope())
602 5ce54458 Panagiotis Kanavos
                {
603 5ce54458 Panagiotis Kanavos
                    //Forgetting to use a sessionscope results in two sessions being created, one by 
604 5ce54458 Panagiotis Kanavos
                    //FirstOrDefault and one by Save()
605 bfc13ed8 Panagiotis Kanavos
                    var state =FileState.FindByFilePath(filePath);
606 ab2f6f79 Panagiotis Kanavos
                    
607 5ce54458 Panagiotis Kanavos
                    //Create a new empty state object if this is a new file
608 5ce54458 Panagiotis Kanavos
                    state = state ?? new FileState();
609 5ce54458 Panagiotis Kanavos
610 5ce54458 Panagiotis Kanavos
                    state.FilePath = filePath;
611 5ce54458 Panagiotis Kanavos
                    state.Checksum = objectInfo.Hash;
612 bfc13ed8 Panagiotis Kanavos
                    state.Version = objectInfo.Version;
613 bfc13ed8 Panagiotis Kanavos
                    state.VersionTimeStamp = objectInfo.VersionTimestamp;
614 bfc13ed8 Panagiotis Kanavos
615 5ce54458 Panagiotis Kanavos
                    state.FileStatus = FileStatus.Unchanged;
616 5ce54458 Panagiotis Kanavos
                    state.OverlayStatus = FileOverlayStatus.Normal;
617 bfc13ed8 Panagiotis Kanavos
                    
618 a0dcfcc9 Panagiotis Kanavos
                  
619 5ce54458 Panagiotis Kanavos
                    //Do the save
620 5ce54458 Panagiotis Kanavos
                    state.Save();
621 5ce54458 Panagiotis Kanavos
                }
622 5ce54458 Panagiotis Kanavos
            });
623 5ce54458 Panagiotis Kanavos
624 283809f3 Panagiotis Kanavos
        }
625 039a89e5 Panagiotis Kanavos
*/
626 039a89e5 Panagiotis Kanavos
        
627 039a89e5 Panagiotis Kanavos
        public void StoreInfo(string path, ObjectInfo objectInfo)
628 1b4a7550 Panagiotis Kanavos
        {
629 1b4a7550 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
630 1b4a7550 Panagiotis Kanavos
                throw new ArgumentNullException("path");
631 1b4a7550 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
632 1b4a7550 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");
633 1b4a7550 Panagiotis Kanavos
            if (objectInfo == null)
634 1b4a7550 Panagiotis Kanavos
                throw new ArgumentNullException("objectInfo", "objectInfo can't be empty");
635 1b4a7550 Panagiotis Kanavos
            Contract.EndContractBlock();
636 1b4a7550 Panagiotis Kanavos
637 039a89e5 Panagiotis Kanavos
            _persistenceAgent.Post(() => StoreInfoDirect(path, objectInfo));
638 1b4a7550 Panagiotis Kanavos
639 1b4a7550 Panagiotis Kanavos
        }
640 1b4a7550 Panagiotis Kanavos
641 039a89e5 Panagiotis Kanavos
        private void StoreInfoDirect(string path, ObjectInfo objectInfo)
642 039a89e5 Panagiotis Kanavos
        {
643 039a89e5 Panagiotis Kanavos
            try
644 039a89e5 Panagiotis Kanavos
            {
645 039a89e5 Panagiotis Kanavos
                
646 039a89e5 Panagiotis Kanavos
                using (var connection = GetConnection())
647 039a89e5 Panagiotis Kanavos
                using (var command = new SQLiteCommand(connection))
648 039a89e5 Panagiotis Kanavos
                {
649 039a89e5 Panagiotis Kanavos
                    if (StateExists(path, connection))
650 039a89e5 Panagiotis Kanavos
                        command.CommandText =
651 3c76f045 Panagiotis Kanavos
                            "update FileState set FileStatus= :fileStatus where FilePath = :path  COLLATE NOCASE ";
652 039a89e5 Panagiotis Kanavos
                    else
653 039a89e5 Panagiotis Kanavos
                    {
654 039a89e5 Panagiotis Kanavos
                        command.CommandText =
655 174bbb6e Panagiotis Kanavos
                            "INSERT INTO FileState (Id,FilePath,Checksum,Version,VersionTimeStamp,ShortHash,FileStatus,OverlayStatus) VALUES (:id,:path,:checksum,:version,:versionTimeStamp,:shortHash,:fileStatus,:overlayStatus)";
656 039a89e5 Panagiotis Kanavos
                        command.Parameters.AddWithValue("id", Guid.NewGuid());
657 039a89e5 Panagiotis Kanavos
                    }
658 039a89e5 Panagiotis Kanavos
659 3c76f045 Panagiotis Kanavos
                    command.Parameters.AddWithValue("path", path);
660 039a89e5 Panagiotis Kanavos
                    command.Parameters.AddWithValue("checksum", objectInfo.Hash);
661 174bbb6e Panagiotis Kanavos
                    command.Parameters.AddWithValue("shortHash", "");
662 039a89e5 Panagiotis Kanavos
                    command.Parameters.AddWithValue("version", objectInfo.Version);
663 039a89e5 Panagiotis Kanavos
                    command.Parameters.AddWithValue("versionTimeStamp",
664 039a89e5 Panagiotis Kanavos
                                                    objectInfo.VersionTimestamp);
665 039a89e5 Panagiotis Kanavos
                    command.Parameters.AddWithValue("fileStatus", FileStatus.Unchanged);
666 039a89e5 Panagiotis Kanavos
                    command.Parameters.AddWithValue("overlayStatus",
667 039a89e5 Panagiotis Kanavos
                                                    FileOverlayStatus.Normal);
668 039a89e5 Panagiotis Kanavos
669 039a89e5 Panagiotis Kanavos
                    var affected = command.ExecuteNonQuery();
670 039a89e5 Panagiotis Kanavos
                    return;
671 039a89e5 Panagiotis Kanavos
                }
672 039a89e5 Panagiotis Kanavos
            }
673 039a89e5 Panagiotis Kanavos
            catch (Exception exc)
674 039a89e5 Panagiotis Kanavos
            {
675 039a89e5 Panagiotis Kanavos
                Log.Error(exc.ToString());
676 039a89e5 Panagiotis Kanavos
                throw;
677 039a89e5 Panagiotis Kanavos
            }
678 039a89e5 Panagiotis Kanavos
        }
679 039a89e5 Panagiotis Kanavos
680 1b4a7550 Panagiotis Kanavos
        private bool StateExists(string filePath,SQLiteConnection connection)
681 1b4a7550 Panagiotis Kanavos
        {
682 3c76f045 Panagiotis Kanavos
            using (var command = new SQLiteCommand("Select count(*) from FileState where FilePath=:path  COLLATE NOCASE", connection))
683 1b4a7550 Panagiotis Kanavos
            {
684 3c76f045 Panagiotis Kanavos
                command.Parameters.AddWithValue("path", filePath);
685 039a89e5 Panagiotis Kanavos
                var result = command.ExecuteScalar();
686 039a89e5 Panagiotis Kanavos
                return ((long)result >= 1);
687 039a89e5 Panagiotis Kanavos
            }
688 1b4a7550 Panagiotis Kanavos
689 1b4a7550 Panagiotis Kanavos
        }
690 283809f3 Panagiotis Kanavos
691 283809f3 Panagiotis Kanavos
        public void SetFileStatus(string path, FileStatus status)
692 ab2f6f79 Panagiotis Kanavos
        {
693 ab2f6f79 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
694 ab2f6f79 Panagiotis Kanavos
                throw new ArgumentNullException("path");
695 ab2f6f79 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
696 ab2f6f79 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");
697 ab2f6f79 Panagiotis Kanavos
            Contract.EndContractBlock();
698 e81dd1f6 Panagiotis Kanavos
            
699 3c76f045 Panagiotis Kanavos
            _persistenceAgent.Post(() => UpdateStatusDirect(path, status));
700 283809f3 Panagiotis Kanavos
        }
701 283809f3 Panagiotis Kanavos
702 0eea575a Panagiotis Kanavos
        public FileStatus GetFileStatus(string path)
703 bfc13ed8 Panagiotis Kanavos
        {
704 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
705 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("path");
706 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
707 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");
708 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
709 cfed7823 Panagiotis Kanavos
710 039a89e5 Panagiotis Kanavos
            
711 039a89e5 Panagiotis Kanavos
            using (var connection = GetConnection())
712 e81dd1f6 Panagiotis Kanavos
            {
713 3c76f045 Panagiotis Kanavos
                var command = new SQLiteCommand("select FileStatus from FileState where FilePath=:path  COLLATE NOCASE", connection);
714 3c76f045 Panagiotis Kanavos
                command.Parameters.AddWithValue("path", path);
715 039a89e5 Panagiotis Kanavos
                
716 025046f1 Panagiotis Kanavos
                var statusValue = command.ExecuteScalar();
717 025046f1 Panagiotis Kanavos
                if (statusValue==null)
718 025046f1 Panagiotis Kanavos
                    return FileStatus.Missing;
719 025046f1 Panagiotis Kanavos
                return (FileStatus)Convert.ToInt32(statusValue);
720 e81dd1f6 Panagiotis Kanavos
            }
721 0eea575a Panagiotis Kanavos
        }
722 0eea575a Panagiotis Kanavos
723 3c76f045 Panagiotis Kanavos
        /// <summary>
724 3c76f045 Panagiotis Kanavos
        /// Deletes the status of the specified file
725 3c76f045 Panagiotis Kanavos
        /// </summary>
726 3c76f045 Panagiotis Kanavos
        /// <param name="path"></param>
727 0eea575a Panagiotis Kanavos
        public void ClearFileStatus(string path)
728 0eea575a Panagiotis Kanavos
        {
729 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
730 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("path");
731 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
732 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");
733 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
734 e81dd1f6 Panagiotis Kanavos
735 e81dd1f6 Panagiotis Kanavos
            _persistenceAgent.Post(() => DeleteDirect(path));   
736 e81dd1f6 Panagiotis Kanavos
        }
737 e81dd1f6 Panagiotis Kanavos
738 3c76f045 Panagiotis Kanavos
        /// <summary>
739 3c76f045 Panagiotis Kanavos
        /// Deletes the status of the specified folder and all its contents
740 3c76f045 Panagiotis Kanavos
        /// </summary>
741 3c76f045 Panagiotis Kanavos
        /// <param name="path"></param>
742 3c76f045 Panagiotis Kanavos
        public void ClearFolderStatus(string path)
743 3c76f045 Panagiotis Kanavos
        {
744 3c76f045 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
745 3c76f045 Panagiotis Kanavos
                throw new ArgumentNullException("path");
746 3c76f045 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
747 3c76f045 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");
748 3c76f045 Panagiotis Kanavos
            Contract.EndContractBlock();
749 3c76f045 Panagiotis Kanavos
750 3c76f045 Panagiotis Kanavos
            _persistenceAgent.Post(() => DeleteFolderDirect(path));   
751 3c76f045 Panagiotis Kanavos
        }
752 3c76f045 Panagiotis Kanavos
753 3c76f045 Panagiotis Kanavos
        public IEnumerable<FileState> GetChildren(FileState fileState)
754 3c76f045 Panagiotis Kanavos
        {
755 3c76f045 Panagiotis Kanavos
            if (fileState == null)
756 3c76f045 Panagiotis Kanavos
                throw new ArgumentNullException("fileState");
757 3c76f045 Panagiotis Kanavos
            Contract.EndContractBlock();
758 3c76f045 Panagiotis Kanavos
759 3c76f045 Panagiotis Kanavos
            var children = from state in FileState.Queryable
760 3c76f045 Panagiotis Kanavos
                           where state.FilePath.StartsWith(fileState.FilePath + "\\")
761 3c76f045 Panagiotis Kanavos
                           select state;
762 3c76f045 Panagiotis Kanavos
            return children;
763 3c76f045 Panagiotis Kanavos
        }
764 3c76f045 Panagiotis Kanavos
765 174bbb6e Panagiotis Kanavos
        public void EnsureFileState(string path)
766 174bbb6e Panagiotis Kanavos
        {
767 174bbb6e Panagiotis Kanavos
            var existingState = GetStateByFilePath(path);
768 174bbb6e Panagiotis Kanavos
            if (existingState != null)
769 174bbb6e Panagiotis Kanavos
                return;
770 174bbb6e Panagiotis Kanavos
            var fileInfo = FileInfoExtensions.FromPath(path);
771 174bbb6e Panagiotis Kanavos
            using (new SessionScope())
772 174bbb6e Panagiotis Kanavos
            {
773 174bbb6e Panagiotis Kanavos
                var newState = FileState.CreateFor(fileInfo);
774 174bbb6e Panagiotis Kanavos
                newState.FileStatus=FileStatus.Missing;
775 174bbb6e Panagiotis Kanavos
                _persistenceAgent.PostAndAwait(newState.CreateAndFlush).Wait();
776 174bbb6e Panagiotis Kanavos
            }
777 174bbb6e Panagiotis Kanavos
778 174bbb6e Panagiotis Kanavos
        }
779 174bbb6e Panagiotis Kanavos
780 e81dd1f6 Panagiotis Kanavos
        private int DeleteDirect(string filePath)
781 e81dd1f6 Panagiotis Kanavos
        {
782 039a89e5 Panagiotis Kanavos
            using (log4net.ThreadContext.Stacks["StatusAgent"].Push("DeleteDirect"))
783 e81dd1f6 Panagiotis Kanavos
            {
784 e81dd1f6 Panagiotis Kanavos
785 039a89e5 Panagiotis Kanavos
                try
786 e81dd1f6 Panagiotis Kanavos
                {
787 e81dd1f6 Panagiotis Kanavos
788 039a89e5 Panagiotis Kanavos
                    
789 039a89e5 Panagiotis Kanavos
                    using (var connection = GetConnection())
790 039a89e5 Panagiotis Kanavos
                    {
791 3c76f045 Panagiotis Kanavos
                        var command = new SQLiteCommand("delete from FileState where FilePath = :path  COLLATE NOCASE",
792 3c76f045 Panagiotis Kanavos
                                                        connection);
793 3c76f045 Panagiotis Kanavos
794 3c76f045 Panagiotis Kanavos
                        command.Parameters.AddWithValue("path", filePath);
795 3c76f045 Panagiotis Kanavos
                        
796 3c76f045 Panagiotis Kanavos
                        var affected = command.ExecuteNonQuery();
797 3c76f045 Panagiotis Kanavos
                        return affected;
798 3c76f045 Panagiotis Kanavos
                    }
799 3c76f045 Panagiotis Kanavos
                }
800 3c76f045 Panagiotis Kanavos
                catch (Exception exc)
801 3c76f045 Panagiotis Kanavos
                {
802 3c76f045 Panagiotis Kanavos
                    Log.Error(exc.ToString());
803 3c76f045 Panagiotis Kanavos
                    throw;
804 3c76f045 Panagiotis Kanavos
                }
805 3c76f045 Panagiotis Kanavos
            }
806 3c76f045 Panagiotis Kanavos
        }
807 3c76f045 Panagiotis Kanavos
808 3c76f045 Panagiotis Kanavos
        private int DeleteFolderDirect(string filePath)
809 3c76f045 Panagiotis Kanavos
        {
810 3c76f045 Panagiotis Kanavos
            using (log4net.ThreadContext.Stacks["StatusAgent"].Push("DeleteDirect"))
811 3c76f045 Panagiotis Kanavos
            {
812 3c76f045 Panagiotis Kanavos
813 3c76f045 Panagiotis Kanavos
                try
814 3c76f045 Panagiotis Kanavos
                {
815 3c76f045 Panagiotis Kanavos
816 3c76f045 Panagiotis Kanavos
                    
817 3c76f045 Panagiotis Kanavos
                    using (var connection = GetConnection())
818 3c76f045 Panagiotis Kanavos
                    {
819 fe62b7f4 Panagiotis Kanavos
                        var command = new SQLiteCommand(@"delete from FileState where FilePath = :path or FilePath like :path || '\%'  COLLATE NOCASE",
820 039a89e5 Panagiotis Kanavos
                                                        connection);
821 039a89e5 Panagiotis Kanavos
822 3c76f045 Panagiotis Kanavos
                        command.Parameters.AddWithValue("path", filePath);
823 039a89e5 Panagiotis Kanavos
                        
824 039a89e5 Panagiotis Kanavos
                        var affected = command.ExecuteNonQuery();
825 039a89e5 Panagiotis Kanavos
                        return affected;
826 039a89e5 Panagiotis Kanavos
                    }
827 039a89e5 Panagiotis Kanavos
                }
828 039a89e5 Panagiotis Kanavos
                catch (Exception exc)
829 039a89e5 Panagiotis Kanavos
                {
830 039a89e5 Panagiotis Kanavos
                    Log.Error(exc.ToString());
831 039a89e5 Panagiotis Kanavos
                    throw;
832 e81dd1f6 Panagiotis Kanavos
                }
833 e81dd1f6 Panagiotis Kanavos
            }
834 0eea575a Panagiotis Kanavos
        }
835 0eea575a Panagiotis Kanavos
836 174bbb6e Panagiotis Kanavos
        public void UpdateFileChecksum(string path, string shortHash, string checksum)
837 cfed7823 Panagiotis Kanavos
        {
838 cfed7823 Panagiotis Kanavos
            if (String.IsNullOrWhiteSpace(path))
839 cfed7823 Panagiotis Kanavos
                throw new ArgumentNullException("path");
840 cfed7823 Panagiotis Kanavos
            if (!Path.IsPathRooted(path))
841 cfed7823 Panagiotis Kanavos
                throw new ArgumentException("The path must be rooted", "path");            
842 cfed7823 Panagiotis Kanavos
            Contract.EndContractBlock();
843 cfed7823 Panagiotis Kanavos
844 174bbb6e Panagiotis Kanavos
            _persistenceAgent.Post(() => FileState.UpdateChecksum(path, shortHash,checksum));
845 0eea575a Panagiotis Kanavos
        }
846 283809f3 Panagiotis Kanavos
847 283809f3 Panagiotis Kanavos
    }
848 5ce54458 Panagiotis Kanavos
849 5ce54458 Panagiotis Kanavos
   
850 0eea575a Panagiotis Kanavos
}