Statistics
| Branch: | Revision:

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

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