Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / StatusKeeper.cs @ 0050438e

History | View | Annotate | Download (7.7 kB)

1
using System;
2
using System.Collections.Concurrent;
3
using System.Collections.Generic;
4
using System.ComponentModel.Composition;
5
using System.Diagnostics;
6
using System.Diagnostics.Contracts;
7
using System.IO;
8
using System.Linq;
9
using System.Security.Cryptography;
10
using System.Text;
11
using System.Threading;
12
using System.Threading.Tasks;
13
using Castle.ActiveRecord;
14
using Castle.ActiveRecord.Framework;
15
using Castle.ActiveRecord.Framework.Config;
16
using Pithos.Interfaces;
17

    
18
namespace Pithos.Core
19
{
20
    [Export(typeof(IStatusChecker)),Export(typeof(IStatusKeeper))]
21
    public class StatusKeeper:IStatusChecker,IStatusKeeper
22
    {
23
        [System.ComponentModel.Composition.Import]
24
        public IPithosSettings Settings { get; set; }
25

    
26
        private BlockingCollection<Action> _statusUpdateQueue = new BlockingCollection<Action>();
27
        //private readonly CancellationToken _cancel=new CancellationToken();
28

    
29
        public StatusKeeper()
30
        {
31
            var source = new XmlConfigurationSource("DbConfig.xml");
32
            ActiveRecordStarter.Initialize(source,typeof(FileState));            
33
            
34
            if (!File.Exists("pithos.db"))
35
                ActiveRecordStarter.CreateSchema();
36

    
37
            Task.Factory.StartNew(ProcessUpdates);
38
        }
39

    
40
        public void ProcessUpdates()
41
        {            
42
            foreach (var action in _statusUpdateQueue.GetConsumingEnumerable())
43
            {
44
                action();
45
            }
46
        }
47

    
48
        public void Stop()
49
        {
50
            _statusUpdateQueue.CompleteAdding();
51
        }
52

    
53
        public FileOverlayStatus GetFileOverlayStatus(string path)
54
        {
55
            try
56
            {
57
                var state = FileState.TryFind(path.ToLower());
58
                return state == null ? FileOverlayStatus.Unversioned : state.OverlayStatus;
59
            }
60
            catch (Exception exc)
61
            {
62
                Trace.TraceError(exc.ToString());
63
                return FileOverlayStatus.Unversioned;
64
            }
65
        }
66

    
67
        public IEnumerable<string> StoreUnversionedFiles(ParallelQuery<string> paths)
68
        {            
69
            var existingFiles = from state in  FileState.Queryable
70
                                    select state.FilePath;
71

    
72
            var newFiles = (from file in paths.Except(existingFiles.AsParallel())
73
                            select new FileState
74
                                       {
75
                                           FilePath = file,
76
                                           OverlayStatus = FileOverlayStatus.Unversioned,
77
                                           FileStatus=FileStatus.Created,     
78
                                           Checksum=Signature.CalculateHash(file)
79
                                       }
80
                           );
81
            
82
            //var files=new ConcurrentBag<string>();
83
            newFiles.ForAll(state=> _statusUpdateQueue.Add(state.Save));
84

    
85
            return newFiles.Select(state => state.FilePath);// files.GetConsumingEnumerable();
86

    
87
        }
88

    
89
/*
90
        private static Task<string> CalculateHashAsync(string path)
91
        {
92

    
93
            string hash;
94
            using (var hasher = MD5.Create())
95
            {
96
                return FileAsync.ReadAllBytes(path)
97
                    .ContinueWith(t => hasher.ComputeHash(t.Result))
98
                    .ContinueWith(t =>
99
                                      {
100
                                          //var hashBuilder = new StringBuilder();
101
                                          return (from byte b in t.Result.AsParallel()
102
                                                  select b.ToString("x2").ToLower()).Aggregate((s1, s2) => s1 + s2);                                         
103
                                      });
104
            }
105
            /*using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true))
106
            {
107
                
108
                stream.ReadAllBytes()
109
                    .ContinueWith(result => hasher.ComputeHash(result.Result))
110
                    .;
111
                var hashBytes = hasher.ComputeHash(stream);
112
                var hashBuilder = new StringBuilder();
113
                foreach (byte b in hasher.ComputeHash(stream))
114
                    hashBuilder.Append(b.ToString("x2").ToLower());
115
                hash = hashBuilder.ToString();
116

    
117
            }
118
            return hash;#1#
119
        }
120
*/
121

    
122

    
123
        private PithosStatus _pithosStatus=PithosStatus.InSynch;       
124

    
125
        public void SetPithosStatus(PithosStatus status)
126
        {
127
            _pithosStatus = status;
128
        }
129

    
130
        public PithosStatus GetPithosStatus()
131
        {
132
            return _pithosStatus;
133
        }
134

    
135
        public void SetFileOverlayStatus(string path, FileOverlayStatus overlayStatus)
136
        {
137
            _statusUpdateQueue.Add(() => 
138
                InnerSetOverlayStatus(path, overlayStatus));
139
        }
140

    
141
        private static void InnerSetOverlayStatus(string path, FileOverlayStatus overlayStatus)
142
        {
143
            var state = FileState.TryFind(path.ToLower());
144
            if (state != null)
145
            {
146
                state.OverlayStatus = overlayStatus;
147
                state.Update();
148
            }
149
            else
150
            {
151
                state = new FileState
152
                            {FilePath = path, OverlayStatus = overlayStatus};
153
                state.Save();
154
            }
155
        }
156

    
157
        public void RemoveFileOverlayStatus(string path)
158
        {
159
            _statusUpdateQueue.Add(() =>
160
                InnerRemoveFileOverlayStatus(path));
161
        }
162

    
163
        private static void InnerRemoveFileOverlayStatus(string path)
164
        {
165
            FileState.DeleteAll(new[] {path});
166
        }
167

    
168
        public void RenameFileOverlayStatus(string oldPath, string newPath)
169
        {
170
            _statusUpdateQueue.Add(() =>
171
                InnerRenameFileOverlayStatus(oldPath, newPath));
172
        }
173

    
174
        private static void InnerRenameFileOverlayStatus(string oldPath, string newPath)
175
        {
176
            var state = FileState.TryFind(oldPath);
177
            if (state == null)
178
            {
179
                Trace.TraceWarning("[NOFILE] Unable to set status for {0}.", oldPath);
180
                return;
181
            }
182
            //NOTE: This will cause problems if path is used as a key in relationships
183
            state.FilePath = newPath;
184
            state.Update();
185
        }
186

    
187
        public void SetFileStatus(string path, FileStatus status)
188
        {
189
            _statusUpdateQueue.Add(() =>
190
                InnerSetFileStatus(path, status));
191
        }
192

    
193
        private static void InnerSetFileStatus(string path, FileStatus status)
194
        {
195
            var state = FileState.TryFind(path.ToLower());
196
            if (state == null)
197
            {
198
                Trace.TraceWarning("[NOFILE] Unable to set status for {0}.", path);
199
                return;
200
            }
201
            state.FileStatus = status;
202
        }
203

    
204
        public FileStatus GetFileStatus(string path)
205
        {
206
            var state = FileState.TryFind(path.ToLower());
207
            return (state==null)?FileStatus.Missing:state.FileStatus ;
208
        }
209

    
210
        public void ClearFileStatus(string path)
211
        {
212
            //TODO:SHOULDN'T need both clear file status and remove overlay status
213
            _statusUpdateQueue.Add(()=>
214
                FileState.DeleteAll(new[] { path.ToLower() }));   
215
        }
216

    
217
        public void UpdateFileChecksum(string path, string checksum)
218
        {
219
            var state = FileState.TryFind(path);
220
            if (state == null)
221
            {
222
                Trace.TraceWarning("[NOFILE] Unable to set checkesum for {0}.",path);
223
                return;
224
            }
225
            state.Checksum = checksum;
226
            state.Update();
227
        }
228
    }
229
}