PollAgent.SynchNow(paths);\r
}\r
\r
-/*\r
- private void ProcessBatchedEvents(Dictionary<string, FileSystemEventArgs[]> fileEvents)\r
- {\r
- StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,String.Format("Uploading {0} files",fileEvents.Count));\r
- //Start with events that do not originate in one of the ignored folders\r
- var initialEvents = from evt in fileEvents\r
- where !IgnorePaths(evt.Key)\r
- select evt;\r
-\r
- IEnumerable<KeyValuePair<string, FileSystemEventArgs[]>> cleanEvents;\r
-\r
- \r
- var selectiveEnabled = Selectives.IsSelectiveEnabled(AccountInfo.AccountKey);\r
- //When selective sync is enabled,\r
- if (selectiveEnabled)\r
- {\r
- //Include all selected items\r
- var selectedEvents = from evt in initialEvents\r
- where Selectives.IsSelected(AccountInfo, evt.Key)\r
- select evt; \r
- //And all folder creations in the unselected folders\r
- var folderCreations = from evt in initialEvents\r
- let folderPath=evt.Key\r
- //The original folder may not exist due to renames. Just make sure that the path is not a file\r
- where !File.Exists(folderPath)\r
- //We only want unselected items\r
- && !Selectives.IsSelected(AccountInfo, folderPath)\r
- //Is there any creation event related to the folder?\r
- && evt.Value.Any(arg => arg.ChangeType == WatcherChangeTypes.Created)\r
- select evt;\r
- cleanEvents = selectedEvents.Union(folderCreations).ToList();\r
- }\r
- //If selective is disabled, only exclude the shared folders \r
- else\r
- {\r
- cleanEvents = (from evt in initialEvents\r
- where !evt.Key.IsSharedTo(AccountInfo)\r
- select evt).ToList();\r
- }\r
-\r
-\r
- foreach (var fileEvent in cleanEvents)\r
- {\r
- //var filePath = fileEvent.Key;\r
- var changes = fileEvent.Value;\r
-\r
- var isNotFile = !File.Exists(fileEvent.Key);\r
- foreach (var change in changes)\r
- {\r
- if (change.ChangeType == WatcherChangeTypes.Renamed)\r
- {\r
- var rename = (MovedEventArgs) change;\r
- _agent.Post(new WorkflowState(change)\r
- {\r
- AccountInfo = AccountInfo,\r
- OldPath = rename.OldFullPath,\r
- OldFileName = Path.GetFileName(rename.OldName),\r
- Path = rename.FullPath,\r
- FileName = Path.GetFileName(rename.Name),\r
- TriggeringChange = rename.ChangeType\r
- });\r
- }\r
- else\r
- {\r
- var isCreation = selectiveEnabled && isNotFile && change.ChangeType == WatcherChangeTypes.Created;\r
- _agent.Post(new WorkflowState(change)\r
- {\r
- AccountInfo = AccountInfo,\r
- Path = change.FullPath,\r
- FileName = Path.GetFileName(change.Name),\r
- TriggeringChange = change.ChangeType,\r
- IsCreation=isCreation\r
- });\r
- }\r
- }\r
- }\r
- StatusNotification.SetPithosStatus(PithosStatus.LocalComplete);\r
- }\r
-*/\r
-\r
public void Start(AccountInfo accountInfo,string rootPath)\r
{\r
if (accountInfo==null)\r
_adapter.Moved += OnMoveEvent;\r
_watcher.EnableRaisingEvents = true;\r
\r
-/* \r
-\r
-\r
-\r
- _agent = Agent<WorkflowState>.Start(inbox =>\r
- {\r
- Action loop = null;\r
- loop = () =>\r
- {\r
- var message = inbox.Receive();\r
- var process=message.Then(Process,inbox.CancellationToken); \r
- inbox.LoopAsync(process,loop,ex=>\r
- Log.ErrorFormat("[ERROR] File Event Processing:\r{0}", ex));\r
- };\r
- loop();\r
- });*/\r
}\r
\r
-/*\r
- private Task<object> Process(WorkflowState state)\r
- {\r
- if (state==null)\r
- throw new ArgumentNullException("state");\r
- Contract.EndContractBlock();\r
-\r
- if (Ignore(state.Path))\r
- return CompletedTask<object>.Default;\r
-\r
- var networkState = NetworkGate.GetNetworkState(state.Path);\r
- //Skip if the file is already being downloaded or uploaded and \r
- //the change is create or modify\r
- if (networkState != NetworkOperation.None &&\r
- (\r
- state.TriggeringChange == WatcherChangeTypes.Created ||\r
- state.TriggeringChange == WatcherChangeTypes.Changed\r
- ))\r
- return CompletedTask<object>.Default;\r
-\r
- try\r
- {\r
- //StatusKeeper.EnsureFileState(state.Path);\r
- \r
- UpdateFileStatus(state);\r
- UpdateOverlayStatus(state);\r
- UpdateLastMD5(state);\r
- WorkflowAgent.Post(state);\r
- }\r
- catch (IOException exc)\r
- {\r
- if (File.Exists(state.Path))\r
- {\r
- Log.WarnFormat("File access error occured, retrying {0}\n{1}", state.Path, exc);\r
- _agent.Post(state);\r
- }\r
- else\r
- {\r
- Log.WarnFormat("File {0} does not exist. Will be ignored\n{1}", state.Path, exc);\r
- }\r
- }\r
- catch (Exception exc)\r
- {\r
- Log.WarnFormat("Error occured while indexing{0}. The file will be skipped\n{1}",\r
- state.Path, exc);\r
- }\r
- return CompletedTask<object>.Default;\r
- }\r
-\r
- public bool Pause\r
- {\r
- get { return _watcher == null || !_watcher.EnableRaisingEvents; }\r
- set\r
- {\r
- if (_watcher != null)\r
- _watcher.EnableRaisingEvents = !value; \r
- }\r
- }\r
-*/\r
\r
public string CachePath { get; set; }\r
\r
- /*private List<string> _selectivePaths = new List<string>();\r
- public List<string> SelectivePaths\r
- {\r
- get { return _selectivePaths; }\r
- set { _selectivePaths = value; }\r
- }\r
-*/\r
public Selectives Selectives { get; set; }\r
\r
-\r
-/*\r
- public void Post(WorkflowState workflowState)\r
- {\r
- if (workflowState == null)\r
- throw new ArgumentNullException("workflowState");\r
- Contract.EndContractBlock();\r
-\r
- _agent.Post(workflowState);\r
- }\r
-\r
- public void Stop()\r
- {\r
- if (_watcher != null)\r
- {\r
- _watcher.Dispose();\r
- }\r
- _watcher = null;\r
-\r
- if (_agent!=null)\r
- _agent.Stop();\r
- }\r
-\r
-*/\r
// Enumerate all files in the Pithos directory except those in the Fragment folder\r
// and files with a .ignore extension\r
public IEnumerable<string> EnumerateFiles(string searchPattern="*")\r
return _ignoreFiles.ContainsKey(filePath.ToLower());\r
}\r
\r
-/* private static bool FoundInRoot(string filePath, string rootPath)\r
- {\r
- //var rootDirectory = new DirectoryInfo(rootPath);\r
-\r
- //If the paths are equal, return true\r
- if (filePath.Equals(rootPath, StringComparison.InvariantCultureIgnoreCase))\r
- return true;\r
-\r
- //If the filepath is below the root path\r
- if (filePath.StartsWith(rootPath,StringComparison.InvariantCulture))\r
- {\r
- //Get the relative path\r
- var relativePath = filePath.Substring(rootPath.Length + 1);\r
- //If the relativePath does NOT contains a path separator, we found a match\r
- return (!relativePath.Contains(@"\"));\r
- }\r
-\r
- //If the filepath is not under the root path, return false\r
- return false; \r
- }*/\r
-\r
\r
private static bool FoundBelowRoot(string filePath, string rootPath,int level)\r
{\r
return false; \r
}\r
\r
- /*\r
- //Post a Change message for renames containing the old and new names\r
- void OnRenameEvent(object sender, RenamedEventArgs e)\r
- {\r
- var oldFullPath = e.OldFullPath;\r
- var fullPath = e.FullPath;\r
- if (Ignore(oldFullPath) || Ignore(fullPath))\r
- return;\r
-\r
- _agent.Post(new WorkflowState\r
- {\r
- AccountInfo=AccountInfo,\r
- OldPath = oldFullPath,\r
- OldFileName = e.OldName,\r
- Path = fullPath,\r
- FileName = e.Name,\r
- TriggeringChange = e.ChangeType\r
- });\r
- }\r
- */\r
\r
//Post a Change message for all events except rename\r
void OnFileEvent(object sender, FileSystemEventArgs e)\r
return state;\r
}\r
\r
- /* private WorkflowState UpdateOverlayStatus(WorkflowState state)\r
- {\r
- if (state==null)\r
- throw new ArgumentNullException("state");\r
- Contract.EndContractBlock();\r
-\r
- if (state.Skip)\r
- return state;\r
-\r
- switch (state.Status)\r
- {\r
- case FileStatus.Created:\r
- this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified,state.ETag).Wait();\r
- break;\r
- case FileStatus.Modified:\r
- this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified, state.ETag).Wait();\r
- break;\r
- case FileStatus.Deleted:\r
- //this.StatusAgent.RemoveFileOverlayStatus(state.Path);\r
- break;\r
- case FileStatus.Renamed:\r
- this.StatusKeeper.ClearFileStatus(state.OldPath);\r
- this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified, state.ETag).Wait();\r
- break;\r
- case FileStatus.Unchanged:\r
- this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Normal, state.ETag).Wait();\r
- break;\r
- }\r
-\r
- if (state.Status == FileStatus.Deleted)\r
- NativeMethods.RaiseChangeNotification(Path.GetDirectoryName(state.Path));\r
- else\r
- NativeMethods.RaiseChangeNotification(state.Path);\r
- return state;\r
- }\r
-\r
-\r
- private WorkflowState UpdateFileChecksum(WorkflowState state)\r
- {\r
- if (state.Skip)\r
- return state;\r
-\r
- if (state.Status == FileStatus.Deleted)\r
- return state;\r
-\r
- var path = state.Path;\r
- //Skip calculation for folders\r
- if (Directory.Exists(path))\r
- return state;\r
-\r
- var info = new FileInfo(path);\r
-\r
- using (StatusNotification.GetNotifier("Hashing {0}", "Finished Hashing {0}", info.Name))\r
- {\r
-\r
- var etag = info.ComputeShortHash(StatusNotification);\r
-\r
- var progress = new Progress<double>(d =>\r
- StatusNotification.Notify(new StatusNotification(String.Format("Hashing {0} of {1}", d, info.Name))));\r
-\r
- string merkleHash = info.CalculateHash(StatusKeeper.BlockSize, StatusKeeper.BlockHash,PollAgent.CancellationToken,progress);\r
- StatusKeeper.UpdateFileChecksum(path, etag, merkleHash);\r
-\r
- state.Hash = merkleHash;\r
- return state;\r
- }\r
- }*/\r
-\r
+ \r
//Does the file exist in the container's local folder?\r
public bool Exists(string relativePath)\r
{\r
public const string MERKLE_EMPTY = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";\r
\r
\r
- //public static string CalculateMD5(FileSystemInfo info)\r
- //{\r
- // if (info==null)\r
- // throw new ArgumentNullException("info");\r
- // if (String.IsNullOrWhiteSpace(info.FullName))\r
- // throw new ArgumentException("info.FullName is empty","info");\r
- // Contract.EndContractBlock();\r
-\r
- // if (info is DirectoryInfo)\r
- // return MD5_EMPTY;\r
-\r
- // return CalculateMD5(info.FullName);\r
- //}\r
-\r
- //public static string CalculateMD5(string path)\r
- //{\r
- // if (String.IsNullOrWhiteSpace(path))\r
- // throw new ArgumentNullException("path");\r
- // Contract.EndContractBlock();\r
-\r
- // //DON'T calculate hashes for folders\r
- // if (Directory.Exists(path))\r
- // return "";\r
- // //TODO: Replace with MD5BlockCalculator\r
- // string hash;\r
- // using (var hasher = new MessageDigestContext(MessageDigest.CreateByName("md5")))\r
- // using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, true))\r
- // {\r
- // var buffer = new byte[BufferSize];\r
- // hasher.Init();\r
- // int read;\r
- // do\r
- // { \r
- // read = stream.Read(buffer, 0, buffer.Length); \r
- // if (read==buffer.Length)\r
- // {\r
- // hasher.Update(buffer); \r
- // }\r
- // else\r
- // {\r
- // var block = new byte[read];\r
- // Buffer.BlockCopy(buffer, 0, block, 0, read);\r
- // hasher.Update(block); \r
- // }\r
- // } while (read>0);\r
- // var hashBytes = hasher.DigestFinal();\r
- // hash = hashBytes.ToHashString();\r
- // }\r
- // return hash;\r
- //}\r
-\r
- \r
-/*\r
- public static string BytesToString(byte[] hashBytes)\r
- {\r
- var shb=new SoapHexBinary(hashBytes);\r
- return shb.ToString();\r
- \r
- }\r
-\r
-\r
- public static byte[] StringToBytes(string hash)\r
- {\r
- var shb=SoapHexBinary.Parse(hash);\r
- return shb.Value;\r
- }\r
-*/\r
-\r
public static byte[] ToBytes(this string hash)\r
{\r
var shb = SoapHexBinary.Parse(hash);\r