Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / StatusKeeper.cs @ 0eea575a

History | View | Annotate | Download (7.1 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.Find(oldPath);
177
            //NOTE: This will cause problems if path is used as a key in relationships
178
            state.FilePath = newPath;
179
            state.Update();
180
        }
181

    
182
        public void SetFileStatus(string path, FileStatus status)
183
        {
184
            _statusUpdateQueue.Add(() =>
185
                InnerSetFileStatus(path, status));
186
        }
187

    
188
        private static void InnerSetFileStatus(string path, FileStatus status)
189
        {
190
            var state = FileState.Find(path);
191
            state.FileStatus = status;
192
        }
193

    
194
        public FileStatus GetFileStatus(string path)
195
        {
196
            var state = FileState.TryFind(path.ToLower());
197
            return (state==null)?FileStatus.Missing:state.FileStatus ;
198
        }
199

    
200
        public void ClearFileStatus(string path)
201
        {
202
            //TODO:SHOULDN'T need both clear file status and remove overlay status
203
            FileState.DeleteAll(new[] { path });   
204
        }
205

    
206
        public void UpdateFileChecksum(string path, string checksum)
207
        {
208
            var state = FileState.Find(path);
209
            state.Checksum = checksum;
210
            state.Update();
211
        }
212
    }
213
}