2 using System.Collections.Concurrent;
3 using System.Collections.Generic;
4 using System.ComponentModel.Composition;
5 using System.Diagnostics;
6 using System.Diagnostics.Contracts;
9 using System.Security.Cryptography;
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;
20 [Export(typeof(IStatusChecker)),Export(typeof(IStatusKeeper))]
21 public class StatusKeeper:IStatusChecker,IStatusKeeper
23 [System.ComponentModel.Composition.Import]
24 public IPithosSettings Settings { get; set; }
26 private BlockingCollection<Action> _statusUpdateQueue = new BlockingCollection<Action>();
27 //private readonly CancellationToken _cancel=new CancellationToken();
31 var source = new XmlConfigurationSource("DbConfig.xml");
32 ActiveRecordStarter.Initialize(source,typeof(FileState));
34 if (!File.Exists("pithos.db"))
35 ActiveRecordStarter.CreateSchema();
37 Task.Factory.StartNew(ProcessUpdates);
40 public void ProcessUpdates()
42 foreach (var action in _statusUpdateQueue.GetConsumingEnumerable())
50 _statusUpdateQueue.CompleteAdding();
53 public FileOverlayStatus GetFileOverlayStatus(string path)
57 var state = FileState.TryFind(path.ToLower());
58 return state == null ? FileOverlayStatus.Unversioned : state.OverlayStatus;
62 Trace.TraceError(exc.ToString());
63 return FileOverlayStatus.Unversioned;
67 public IEnumerable<string> StoreUnversionedFiles(ParallelQuery<string> paths)
69 var existingFiles = from state in FileState.Queryable
70 select state.FilePath;
72 var newFiles = (from file in paths.Except(existingFiles.AsParallel())
76 OverlayStatus = FileOverlayStatus.Unversioned,
77 FileStatus=FileStatus.Created,
78 Checksum=Signature.CalculateHash(file)
82 //var files=new ConcurrentBag<string>();
83 newFiles.ForAll(state=> _statusUpdateQueue.Add(state.Save));
85 return newFiles.Select(state => state.FilePath);// files.GetConsumingEnumerable();
90 private static Task<string> CalculateHashAsync(string path)
94 using (var hasher = MD5.Create())
96 return FileAsync.ReadAllBytes(path)
97 .ContinueWith(t => hasher.ComputeHash(t.Result))
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);
105 /*using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true))
108 stream.ReadAllBytes()
109 .ContinueWith(result => hasher.ComputeHash(result.Result))
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();
123 private PithosStatus _pithosStatus=PithosStatus.InSynch;
125 public void SetPithosStatus(PithosStatus status)
127 _pithosStatus = status;
130 public PithosStatus GetPithosStatus()
132 return _pithosStatus;
135 public void SetFileOverlayStatus(string path, FileOverlayStatus overlayStatus)
137 _statusUpdateQueue.Add(() =>
138 InnerSetOverlayStatus(path, overlayStatus));
141 private static void InnerSetOverlayStatus(string path, FileOverlayStatus overlayStatus)
143 var state = FileState.TryFind(path.ToLower());
146 state.OverlayStatus = overlayStatus;
151 state = new FileState
152 {FilePath = path, OverlayStatus = overlayStatus};
157 public void RemoveFileOverlayStatus(string path)
159 _statusUpdateQueue.Add(() =>
160 InnerRemoveFileOverlayStatus(path));
163 private static void InnerRemoveFileOverlayStatus(string path)
165 FileState.DeleteAll(new[] {path});
168 public void RenameFileOverlayStatus(string oldPath, string newPath)
170 _statusUpdateQueue.Add(() =>
171 InnerRenameFileOverlayStatus(oldPath, newPath));
174 private static void InnerRenameFileOverlayStatus(string oldPath, string newPath)
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;
182 public void SetFileStatus(string path, FileStatus status)
184 _statusUpdateQueue.Add(() =>
185 InnerSetFileStatus(path, status));
188 private static void InnerSetFileStatus(string path, FileStatus status)
190 var state = FileState.Find(path);
191 state.FileStatus = status;
194 public FileStatus GetFileStatus(string path)
196 var state = FileState.TryFind(path.ToLower());
197 return (state==null)?FileStatus.Missing:state.FileStatus ;
200 public void ClearFileStatus(string path)
202 //TODO:SHOULDN'T need both clear file status and remove overlay status
203 FileState.DeleteAll(new[] { path });
206 public void UpdateFileChecksum(string path, string checksum)
208 var state = FileState.Find(path);
209 state.Checksum = checksum;