-#region
-/* -----------------------------------------------------------------------
- * <copyright file="PithosMonitor.cs" company="GRNet">
- *
- * Copyright 2011-2012 GRNET S.A. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and
- * documentation are those of the authors and should not be
- * interpreted as representing official policies, either expressed
- * or implied, of GRNET S.A.
- * </copyright>
- * -----------------------------------------------------------------------
- */
-#endregion
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Threading;
-using System.Threading.Tasks;
-using Pithos.Core.Agents;
-using Pithos.Interfaces;
-using Pithos.Network;
-using log4net;
-
-namespace Pithos.Core
-{
- [Export(typeof(PithosMonitor))]
- public class PithosMonitor:IDisposable
- {
- private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- private int _blockSize;
- private string _blockHash;
-
- [Import]
- public IPithosSettings Settings{get;set;}
-
- private IStatusKeeper _statusKeeper;
-
- [Import]
- public IStatusKeeper StatusKeeper
- {
- get { return _statusKeeper; }
- set
- {
- _statusKeeper = value;
- FileAgent.StatusKeeper = value;
- }
- }
-
-
-
-
- private IPithosWorkflow _workflow;
-
- [Import]
- public IPithosWorkflow Workflow
- {
- get { return _workflow; }
- set
- {
- _workflow = value;
- FileAgent.Workflow = value;
- }
- }
-
- public ICloudClient CloudClient { get; set; }
-
- public IStatusNotification StatusNotification { get; set; }
-
- //[Import]
- public FileAgent FileAgent { get; private set; }
-
-/*
- private WorkflowAgent _workflowAgent;
-
- [Import]
- public WorkflowAgent WorkflowAgent
- {
- get { return _workflowAgent; }
- set
- {
- _workflowAgent = value;
- //FileAgent.WorkflowAgent = value;
- }
- }
-*/
-
- [Import]
- public NetworkAgent NetworkAgent { get; set; }
-
- private PollAgent _pollAgent;
-
- [Import]
- public PollAgent PollAgent
- {
- get { return _pollAgent; }
- set
- {
- _pollAgent = value;
- FileAgent.PollAgent = value;
- }
- }
-
- private Selectives _selectives;
-
- [Import]
- public Selectives Selectives
- {
- get { return _selectives; }
- set
- {
- _selectives = value;
- FileAgent.Selectives = value;
- }
- }
-
- public string UserName { get; set; }
- private string _apiKey;
- public string ApiKey
- {
- get { return _apiKey; }
- set
- {
- _apiKey = value;
- if (_accountInfo != null)
- _accountInfo.Token = value;
- }
- }
-
- private AccountInfo _accountInfo;
-
- public AccountInfo Account
- {
- get { return _accountInfo; }
- }
-
-
-
-
-
- public bool Pause { get; set; }
- /*public bool Pause
- {
- get { return FileAgent.Pause; }
- set
- {
- FileAgent.Pause = value;
- }
- }*/
-
- private string _rootPath;
- public string RootPath
- {
- get { return _rootPath; }
- set
- {
- _rootPath = String.IsNullOrWhiteSpace(value)
- ? String.Empty
- : value.ToLower();
- }
- }
-
-
- CancellationTokenSource _cancellationSource;
-
- public PithosMonitor()
- {
- FileAgent = new FileAgent();
- }
- private bool _started;
-
- public void Start()
- {
- if (String.IsNullOrWhiteSpace(ApiKey))
- throw new InvalidOperationException("The ApiKey is empty");
- if (String.IsNullOrWhiteSpace(UserName))
- throw new InvalidOperationException("The UserName is empty");
- if (String.IsNullOrWhiteSpace(AuthenticationUrl))
- throw new InvalidOperationException("The Authentication url is empty");
- Contract.EndContractBlock();
-
- //If the account doesn't have a valid path, don't start monitoring but don't throw either
- if (String.IsNullOrWhiteSpace(RootPath))
- //TODO; Warn user?
- return;
-
- //WorkflowAgent.StatusNotification = StatusNotification;
-
- StatusNotification.NotifyChange("Starting");
- if (_started)
- {
- if (!_cancellationSource.IsCancellationRequested)
- return;
- }
- _cancellationSource = new CancellationTokenSource();
-
- lock (this)
- {
- CloudClient = new CloudFilesClient(UserName, ApiKey)
- {UsePithos = true, AuthenticationUrl = AuthenticationUrl};
- _accountInfo = CloudClient.Authenticate();
- }
- _accountInfo.SiteUri = AuthenticationUrl;
- _accountInfo.AccountPath = RootPath;
-
-
- var pithosFolder = Path.Combine(RootPath, FolderConstants.PithosContainer);
- if (!Directory.Exists(pithosFolder))
- Directory.CreateDirectory(pithosFolder);
- //Create the cache folder and ensure it is hidden
- CreateHiddenFolder(RootPath, FolderConstants.CacheFolder);
-
- var policy=CloudClient.GetAccountPolicies(_accountInfo);
-
- StatusNotification.NotifyAccount(policy);
- EnsurePithosContainers();
-
- StatusKeeper.BlockHash = _blockHash;
- StatusKeeper.BlockSize = _blockSize;
-
- StatusKeeper.StartProcessing(_cancellationSource.Token);
- CleanupUnselectedStates();
- IndexLocalFiles();
- //Extract the URIs from the string collection
- var settings = Settings.Accounts.First(s => s.AccountKey == _accountInfo.AccountKey );
-
- var selectiveUrls=settings.SelectiveFolders.Cast<string>().Select(url => new Uri(url,UriKind.RelativeOrAbsolute))
- .Where(uri=>uri.IsAbsoluteUri).ToArray();
-
- SetSelectivePaths(selectiveUrls,null,null);
-
- StartWatcherAgent();
-
- StartNetworkAgent();
-
- //WorkflowAgent.RestartInterruptedFiles(_accountInfo);
- _started = true;
- }
-
- private void EnsurePithosContainers()
- {
-
- //Create the two default containers if they are missing
- var pithosContainers = new List<string>{ FolderConstants.TrashContainer,FolderConstants.PithosContainer};
- foreach (var container in pithosContainers)
- {
- var info=CloudClient.GetContainerInfo(UserName, container);
- if (info == ContainerInfo.Empty)
- {
- CloudClient.CreateContainer(UserName, container);
- info = CloudClient.GetContainerInfo(UserName, container);
- }
- _blockSize = info.BlockSize;
- _blockHash = info.BlockHash;
- _accountInfo.BlockSize = _blockSize;
- _accountInfo.BlockHash = _blockHash;
- }
- }
-
- public string AuthenticationUrl { get; set; }
-
- private void IndexLocalFiles()
- {
- using (ThreadContext.Stacks["Operation"].Push("Indexing local files"))
- {
-
- try
- {
- //StatusNotification.NotifyChange("Indexing Local Files");
- Log.Info("Start local indexing");
- StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,"Indexing Local Files");
-
- var cachePath = Path.Combine(RootPath, FolderConstants.CacheFolder);
- var directory = new DirectoryInfo(RootPath);
- var files =
- from file in directory.EnumerateFiles("*", SearchOption.AllDirectories)
- where !file.FullName.StartsWith(cachePath, StringComparison.InvariantCultureIgnoreCase) &&
- !file.Extension.Equals("ignore", StringComparison.InvariantCultureIgnoreCase)
- select file;
- StatusKeeper.ProcessExistingFiles(files);
-
- }
- catch (Exception exc)
- {
- Log.Error("[ERROR]", exc);
- }
- finally
- {
- Log.Info("[END]");
- }
- StatusNotification.SetPithosStatus(PithosStatus.LocalComplete,"Indexing Completed");
- }
- }
-
-
-
-
-
- /* private void StartWorkflowAgent()
- {
- WorkflowAgent.StatusNotification = StatusNotification;
-
-/* //On Vista and up we can check for a network connection
- bool connected=Environment.OSVersion.Version.Major < 6 || NetworkListManager.IsConnectedToInternet;
- //If we are not connected retry later
- if (!connected)
- {
- Task.Factory.StartNewDelayed(10000, StartWorkflowAgent);
- return;
- }#1#
-
- try
- {
- WorkflowAgent.Start();
- }
- catch (Exception)
- {
- //Faild to authenticate due to network or account error
- //Retry after a while
- Task.Factory.StartNewDelayed(10000, StartWorkflowAgent);
- }
- }*/
-
-
- private void StartNetworkAgent()
- {
- NetworkAgent.StatusNotification = StatusNotification;
-
- //TODO: The Network and Poll agents are not account specific
- //They should be moved outside PithosMonitor
-/*
- NetworkAgent.Start();
-*/
-
- PollAgent.AddAccount(_accountInfo);
-
- PollAgent.StatusNotification = StatusNotification;
-
- PollAgent.PollRemoteFiles();
- }
-
- //Make sure a hidden cache folder exists to store partial downloads
- private static void CreateHiddenFolder(string rootPath, string folderName)
- {
- if (String.IsNullOrWhiteSpace(rootPath))
- throw new ArgumentNullException("rootPath");
- if (!Path.IsPathRooted(rootPath))
- throw new ArgumentException("rootPath");
- if (String.IsNullOrWhiteSpace(folderName))
- throw new ArgumentNullException("folderName");
- Contract.EndContractBlock();
-
- var folder = Path.Combine(rootPath, folderName);
- if (!Directory.Exists(folder))
- {
- var info = Directory.CreateDirectory(folder);
- info.Attributes |= FileAttributes.Hidden;
-
- Log.InfoFormat("Created cache Folder: {0}", folder);
- }
- else
- {
- var info = new DirectoryInfo(folder);
- if ((info.Attributes & FileAttributes.Hidden) == 0)
- {
- info.Attributes |= FileAttributes.Hidden;
- Log.InfoFormat("Reset cache folder to hidden: {0}", folder);
- }
- }
- }
-
-
-
-
- private void StartWatcherAgent()
- {
- if (Log.IsDebugEnabled)
- Log.DebugFormat("Start Folder Monitoring [{0}]",RootPath);
-
- AgentLocator<FileAgent>.Register(FileAgent,RootPath);
-
- FileAgent.IdleTimeout = Settings.FileIdleTimeout;
- FileAgent.StatusKeeper = StatusKeeper;
- FileAgent.StatusNotification = StatusNotification;
- FileAgent.Workflow = Workflow;
- FileAgent.CachePath = Path.Combine(RootPath, FolderConstants.CacheFolder);
- FileAgent.Start(_accountInfo, RootPath);
- }
-
- public void Stop()
- {
-/*
- AgentLocator<FileAgent>.Remove(RootPath);
-
- if (FileAgent!=null)
- FileAgent.Stop();
- FileAgent = null;
-*/
- }
-
-
- ~PithosMonitor()
- {
- Dispose(false);
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- Stop();
- }
- }
-
-
- public void MoveFileStates(string oldPath, string newPath)
- {
- if (String.IsNullOrWhiteSpace(oldPath))
- throw new ArgumentNullException("oldPath");
- if (!Path.IsPathRooted(oldPath))
- throw new ArgumentException("oldPath must be an absolute path","oldPath");
- if (string.IsNullOrWhiteSpace(newPath))
- throw new ArgumentNullException("newPath");
- if (!Path.IsPathRooted(newPath))
- throw new ArgumentException("newPath must be an absolute path","newPath");
- Contract.EndContractBlock();
-
- StatusKeeper.ChangeRoots(oldPath, newPath);
- }
-
- private void CleanupUnselectedStates()
- {
- //var settings = Settings.Accounts.First(s => s.AccountKey == _accountInfo.AccountKey);
- if (!Selectives.IsSelectiveEnabled(_accountInfo.AccountKey)) return;
-
- List<string> selectivePaths;
- if (Selectives.SelectivePaths.TryGetValue(_accountInfo.AccountKey, out selectivePaths))
+#region\r
+/* -----------------------------------------------------------------------\r
+ * <copyright file="PithosMonitor.cs" company="GRNet">\r
+ * \r
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * The views and conclusions contained in the software and\r
+ * documentation are those of the authors and should not be\r
+ * interpreted as representing official policies, either expressed\r
+ * or implied, of GRNET S.A.\r
+ * </copyright>\r
+ * -----------------------------------------------------------------------\r
+ */\r
+#endregion\r
+using System;\r
+using System.Collections.Generic;\r
+using System.ComponentModel.Composition;\r
+using System.Diagnostics.Contracts;\r
+using System.IO;\r
+using System.Linq;\r
+using System.Reflection;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+using Pithos.Core.Agents;\r
+using Pithos.Interfaces;\r
+using Pithos.Network;\r
+using log4net;\r
+\r
+namespace Pithos.Core\r
+{\r
+ [Export(typeof(PithosMonitor))]\r
+ public class PithosMonitor:IDisposable\r
+ {\r
+ private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);\r
+\r
+ private int _blockSize;\r
+ private string _blockHash;\r
+\r
+ [Import]\r
+ public IPithosSettings Settings{get;set;}\r
+\r
+ private IStatusKeeper _statusKeeper;\r
+\r
+ [Import]\r
+ public IStatusKeeper StatusKeeper\r
+ {\r
+ get { return _statusKeeper; }\r
+ set\r
+ {\r
+ _statusKeeper = value;\r
+ FileAgent.StatusKeeper = value;\r
+ }\r
+ }\r
+\r
+\r
+\r
+\r
+ private IPithosWorkflow _workflow;\r
+\r
+ [Import]\r
+ public IPithosWorkflow Workflow\r
+ {\r
+ get { return _workflow; }\r
+ set\r
+ {\r
+ _workflow = value;\r
+ FileAgent.Workflow = value;\r
+ }\r
+ }\r
+\r
+ public ICloudClient CloudClient { get; set; }\r
+\r
+ public IStatusNotification StatusNotification { get; set; }\r
+\r
+ //[Import]\r
+ public FileAgent FileAgent { get; private set; }\r
+\r
+/*\r
+ private WorkflowAgent _workflowAgent;\r
+\r
+ [Import]\r
+ public WorkflowAgent WorkflowAgent\r
+ {\r
+ get { return _workflowAgent; }\r
+ set\r
+ {\r
+ _workflowAgent = value;\r
+ //FileAgent.WorkflowAgent = value;\r
+ }\r
+ }\r
+*/\r
+ \r
+ [Import]\r
+ public NetworkAgent NetworkAgent { get; set; }\r
+\r
+ private PollAgent _pollAgent;\r
+\r
+ [Import]\r
+ public PollAgent PollAgent\r
+ {\r
+ get { return _pollAgent; }\r
+ set\r
+ {\r
+ _pollAgent = value;\r
+ FileAgent.PollAgent = value;\r
+ }\r
+ }\r
+\r
+ private Selectives _selectives;\r
+\r
+ [Import]\r
+ public Selectives Selectives\r
+ {\r
+ get { return _selectives; }\r
+ set\r
+ {\r
+ _selectives = value;\r
+ FileAgent.Selectives = value;\r
+ }\r
+ }\r
+\r
+ public string UserName { get; set; }\r
+ private string _apiKey;\r
+ public string ApiKey\r
+ {\r
+ get { return _apiKey; }\r
+ set\r
+ {\r
+ _apiKey = value;\r
+ if (_accountInfo != null)\r
+ _accountInfo.Token = value;\r
+ }\r
+ }\r
+\r
+ private AccountInfo _accountInfo;\r
+\r
+ public AccountInfo Account\r
+ {\r
+ get { return _accountInfo; }\r
+ }\r
+\r
+\r
+\r
+\r
+\r
+ public bool Pause { get; set; } \r
+ /*public bool Pause\r
+ {\r
+ get { return FileAgent.Pause; }\r
+ set\r
+ {\r
+ FileAgent.Pause = value;\r
+ }\r
+ }*/\r
+\r
+ private string _rootPath;\r
+ public string RootPath\r
+ {\r
+ get { return _rootPath; }\r
+ set \r
+ {\r
+ _rootPath = String.IsNullOrWhiteSpace(value) \r
+ ? String.Empty \r
+ : value.ToLower();\r
+ }\r
+ }\r
+\r
+\r
+ CancellationTokenSource _cancellationSource;\r
+\r
+ public PithosMonitor()\r
+ {\r
+ FileAgent = new FileAgent(); \r
+ }\r
+ private bool _started;\r
+\r
+ public void Start()\r
+ { \r
+ if (String.IsNullOrWhiteSpace(ApiKey))\r
+ throw new InvalidOperationException("The ApiKey is empty");\r
+ if (String.IsNullOrWhiteSpace(UserName))\r
+ throw new InvalidOperationException("The UserName is empty");\r
+ if (String.IsNullOrWhiteSpace(AuthenticationUrl))\r
+ throw new InvalidOperationException("The Authentication url is empty");\r
+ Contract.EndContractBlock();\r
+\r
+ //If the account doesn't have a valid path, don't start monitoring but don't throw either\r
+ if (String.IsNullOrWhiteSpace(RootPath))\r
+ //TODO; Warn user?\r
+ return;\r
+\r
+ //WorkflowAgent.StatusNotification = StatusNotification;\r
+\r
+ StatusNotification.NotifyChange("Starting");\r
+ if (_started)\r
+ {\r
+ if (!_cancellationSource.IsCancellationRequested)\r
+ return;\r
+ }\r
+ _cancellationSource = new CancellationTokenSource();\r
+\r
+ lock (this)\r
+ {\r
+ CloudClient = new CloudFilesClient(UserName, ApiKey)\r
+ {UsePithos = true, AuthenticationUrl = AuthenticationUrl};\r
+ _accountInfo = CloudClient.Authenticate();\r
+ }\r
+ _accountInfo.SiteUri = AuthenticationUrl;\r
+ _accountInfo.AccountPath = RootPath;\r
+\r
+\r
+ var pithosFolder = Path.Combine(RootPath, FolderConstants.PithosContainer);\r
+ if (!Directory.Exists(pithosFolder))\r
+ Directory.CreateDirectory(pithosFolder);\r
+ //Create the cache folder and ensure it is hidden\r
+ CreateHiddenFolder(RootPath, FolderConstants.CacheFolder);\r
+\r
+ var policy=CloudClient.GetAccountPolicies(_accountInfo);\r
+\r
+ StatusNotification.NotifyAccount(policy);\r
+ EnsurePithosContainers();\r
+ \r
+ StatusKeeper.BlockHash = _blockHash;\r
+ StatusKeeper.BlockSize = _blockSize;\r
+ \r
+ StatusKeeper.StartProcessing(_cancellationSource.Token);\r
+ CleanupUnselectedStates();\r
+ IndexLocalFiles();\r
+ //Extract the URIs from the string collection\r
+ var settings = Settings.Accounts.First(s => s.AccountKey == _accountInfo.AccountKey );\r
+ \r
+ var selectiveUrls=settings.SelectiveFolders.Cast<string>().Select(url => new Uri(url,UriKind.RelativeOrAbsolute))\r
+ .Where(uri=>uri.IsAbsoluteUri).ToArray();\r
+\r
+ SetSelectivePaths(selectiveUrls,null,null);\r
+ \r
+ StartWatcherAgent();\r
+\r
+ StartNetworkAgent();\r
+ \r
+ //WorkflowAgent.RestartInterruptedFiles(_accountInfo);\r
+ _started = true;\r
+ }\r
+\r
+ private void EnsurePithosContainers()\r
+ {\r
+\r
+ //Create the two default containers if they are missing\r
+ var pithosContainers = new List<string>{ FolderConstants.TrashContainer,FolderConstants.PithosContainer};\r
+ foreach (var container in pithosContainers)\r
+ { \r
+ var info=CloudClient.GetContainerInfo(UserName, container);\r
+ if (info == ContainerInfo.Empty)\r
+ {\r
+ CloudClient.CreateContainer(UserName, container);\r
+ info = CloudClient.GetContainerInfo(UserName, container);\r
+ }\r
+ _blockSize = info.BlockSize;\r
+ _blockHash = info.BlockHash;\r
+ _accountInfo.BlockSize = _blockSize;\r
+ _accountInfo.BlockHash = _blockHash;\r
+ }\r
+ }\r
+\r
+ public string AuthenticationUrl { get; set; }\r
+\r
+ private void IndexLocalFiles()\r
+ {\r
+ using (ThreadContext.Stacks["Operation"].Push("Indexing local files"))\r
+ {\r
+ \r
+ try\r
+ {\r
+ //StatusNotification.NotifyChange("Indexing Local Files");\r
+ Log.Info("Start local indexing");\r
+ StatusNotification.SetPithosStatus(PithosStatus.LocalSyncing,"Indexing Local Files"); \r
+\r
+ var cachePath = Path.Combine(RootPath, FolderConstants.CacheFolder);\r
+ var directory = new DirectoryInfo(RootPath);\r
+ var files =\r
+ from file in directory.EnumerateFiles("*", SearchOption.AllDirectories)\r
+ where !file.FullName.StartsWith(cachePath, StringComparison.InvariantCultureIgnoreCase) &&\r
+ !file.Extension.Equals("ignore", StringComparison.InvariantCultureIgnoreCase)\r
+ select file;\r
+ StatusKeeper.ProcessExistingFiles(files);\r
+\r
+ }\r
+ catch (Exception exc)\r
+ {\r
+ Log.Error("[ERROR]", exc);\r
+ }\r
+ finally\r
+ {\r
+ Log.Info("[END]");\r
+ }\r
+ StatusNotification.SetPithosStatus(PithosStatus.LocalComplete,"Indexing Completed");\r
+ }\r
+ }\r
+\r
+ \r
+ \r
+\r
+\r
+ /* private void StartWorkflowAgent()\r
+ {\r
+ WorkflowAgent.StatusNotification = StatusNotification;\r
+\r
+/* //On Vista and up we can check for a network connection\r
+ bool connected=Environment.OSVersion.Version.Major < 6 || NetworkListManager.IsConnectedToInternet;\r
+ //If we are not connected retry later\r
+ if (!connected)\r
+ {\r
+ Task.Factory.StartNewDelayed(10000, StartWorkflowAgent);\r
+ return;\r
+ }#1#\r
+\r
+ try\r
+ {\r
+ WorkflowAgent.Start(); \r
+ }\r
+ catch (Exception)\r
+ {\r
+ //Faild to authenticate due to network or account error\r
+ //Retry after a while\r
+ Task.Factory.StartNewDelayed(10000, StartWorkflowAgent);\r
+ }\r
+ }*/\r
+\r
+\r
+ private void StartNetworkAgent()\r
+ {\r
+ NetworkAgent.StatusNotification = StatusNotification;\r
+\r
+ //TODO: The Network and Poll agents are not account specific\r
+ //They should be moved outside PithosMonitor\r
+/*\r
+ NetworkAgent.Start();\r
+*/\r
+\r
+ PollAgent.AddAccount(_accountInfo);\r
+\r
+ PollAgent.StatusNotification = StatusNotification;\r
+\r
+ PollAgent.PollRemoteFiles();\r
+ }\r
+\r
+ //Make sure a hidden cache folder exists to store partial downloads\r
+ private static void CreateHiddenFolder(string rootPath, string folderName)\r
+ {\r
+ if (String.IsNullOrWhiteSpace(rootPath))\r
+ throw new ArgumentNullException("rootPath");\r
+ if (!Path.IsPathRooted(rootPath))\r
+ throw new ArgumentException("rootPath");\r
+ if (String.IsNullOrWhiteSpace(folderName))\r
+ throw new ArgumentNullException("folderName");\r
+ Contract.EndContractBlock();\r
+\r
+ var folder = Path.Combine(rootPath, folderName);\r
+ if (!Directory.Exists(folder))\r
+ {\r
+ var info = Directory.CreateDirectory(folder);\r
+ info.Attributes |= FileAttributes.Hidden;\r
+\r
+ Log.InfoFormat("Created cache Folder: {0}", folder);\r
+ }\r
+ else\r
+ {\r
+ var info = new DirectoryInfo(folder);\r
+ if ((info.Attributes & FileAttributes.Hidden) == 0)\r
+ {\r
+ info.Attributes |= FileAttributes.Hidden;\r
+ Log.InfoFormat("Reset cache folder to hidden: {0}", folder);\r
+ } \r
+ }\r
+ }\r
+\r
+ \r
+\r
+\r
+ private void StartWatcherAgent()\r
+ {\r
+ if (Log.IsDebugEnabled)\r
+ Log.DebugFormat("Start Folder Monitoring [{0}]",RootPath);\r
+\r
+ AgentLocator<FileAgent>.Register(FileAgent,RootPath);\r
+ \r
+ FileAgent.IdleTimeout = Settings.FileIdleTimeout;\r
+ FileAgent.StatusKeeper = StatusKeeper;\r
+ FileAgent.StatusNotification = StatusNotification;\r
+ FileAgent.Workflow = Workflow;\r
+ FileAgent.CachePath = Path.Combine(RootPath, FolderConstants.CacheFolder);\r
+ FileAgent.Start(_accountInfo, RootPath);\r
+ }\r
+\r
+ public void Stop()\r
+ {\r
+/*\r
+ AgentLocator<FileAgent>.Remove(RootPath);\r
+\r
+ if (FileAgent!=null)\r
+ FileAgent.Stop();\r
+ FileAgent = null;\r
+*/\r
+ }\r
+\r
+\r
+ ~PithosMonitor()\r
+ {\r
+ Dispose(false);\r
+ }\r
+\r
+ public void Dispose()\r
+ {\r
+ Dispose(true);\r
+ GC.SuppressFinalize(this);\r
+ }\r
+\r
+ protected virtual void Dispose(bool disposing)\r
+ {\r
+ if (disposing)\r
+ {\r
+ Stop();\r
+ }\r
+ }\r
+\r
+\r
+ public void MoveFileStates(string oldPath, string newPath)\r
+ {\r
+ if (String.IsNullOrWhiteSpace(oldPath))\r
+ throw new ArgumentNullException("oldPath");\r
+ if (!Path.IsPathRooted(oldPath))\r
+ throw new ArgumentException("oldPath must be an absolute path","oldPath");\r
+ if (string.IsNullOrWhiteSpace(newPath))\r
+ throw new ArgumentNullException("newPath");\r
+ if (!Path.IsPathRooted(newPath))\r
+ throw new ArgumentException("newPath must be an absolute path","newPath");\r
+ Contract.EndContractBlock();\r
+\r
+ StatusKeeper.ChangeRoots(oldPath, newPath);\r
+ }\r
+\r
+ private void CleanupUnselectedStates()\r
+ {\r
+ //var settings = Settings.Accounts.First(s => s.AccountKey == _accountInfo.AccountKey);\r
+ if (!Selectives.IsSelectiveEnabled(_accountInfo.AccountKey)) return;\r
+\r
+ List<string> selectivePaths;\r
+ if (Selectives.SelectivePaths.TryGetValue(_accountInfo.AccountKey, out selectivePaths))\r
{\r
var statePaths= FileState.Queryable.Select(state => state.FilePath).ToList();\r
- var removedPaths = statePaths.Where(sp => !selectivePaths.Any(sp.IsAtOrBelow));
-
- UnversionSelectivePaths(removedPaths.ToList());
- }
- else
- {
- StatusKeeper.ClearFolderStatus(Account.AccountPath);
- }
- }
-
- public void SetSelectivePaths(Uri[] uris,Uri[] added, Uri[] removed)
- {
- //Convert the uris to paths
- //var selectivePaths = UrisToFilePaths(uris);
-
- var selectiveUri = uris.ToList();
- this.Selectives.SetSelectedUris(_accountInfo,selectiveUri);
-
- var removedPaths = UrisToFilePaths(removed);
- UnversionSelectivePaths(removedPaths);
-
- }
-
- /// <summary>
- /// Mark all unselected paths as Unversioned
- /// </summary>
- /// <param name="removed"></param>
- private void UnversionSelectivePaths(List<string> removed)
- {
- if (removed == null)
- return;
-
- //Ensure we remove any file state below the deleted folders
- FileState.UnversionPaths(removed);
- }
-
-
- /// <summary>
- /// Return a list of absolute filepaths from a list of Uris
- /// </summary>
- /// <param name="uris"></param>
- /// <returns></returns>
- public List<string> UrisToFilePaths(IEnumerable<Uri> uris)
- {
- if (uris == null)
- return new List<string>();
-
- var own = (from uri in uris
- where uri.ToString().StartsWith(_accountInfo.StorageUri.ToString())
- let relativePath = _accountInfo.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()
- //Trim the account name
- select Path.Combine(RootPath, relativePath.After(_accountInfo.UserName + '\\'))).ToList();
- var others= (from uri in uris
- where !uri.ToString().StartsWith(_accountInfo.StorageUri.ToString())
- let relativePath = _accountInfo.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()
- //Trim the account name
- select Path.Combine(RootPath,"others-shared", relativePath)).ToList();
- return own.Union(others).ToList();
- }
-
-
- public ObjectInfo GetObjectInfo(string filePath)
- {
- if (String.IsNullOrWhiteSpace(filePath))
- throw new ArgumentNullException("filePath");
- Contract.EndContractBlock();
-
- var file=new FileInfo(filePath);
- string relativeUrl;//=file.AsRelativeUrlTo(this.RootPath);
- var relativePath = file.AsRelativeTo(RootPath);
-
- string accountName,container;
-
- var parts=relativePath.Split('\\');
-
- var accountInfo = _accountInfo;
- if (relativePath.StartsWith(FolderConstants.OthersFolder))
- {
- accountName = parts[1];
- container = parts[2];
- relativeUrl = String.Join("/", parts.Splice(3));
- //Create the root URL for the target account
- var oldName = UserName;
- var absoluteUri = _accountInfo.StorageUri.AbsoluteUri;
- var nameIndex=absoluteUri.IndexOf(oldName, StringComparison.Ordinal);
- var root=absoluteUri.Substring(0, nameIndex);
-
- accountInfo = new AccountInfo
- {
- UserName = accountName,
- AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),
- StorageUri = new Uri(root + accountName),
- BlockHash=accountInfo.BlockHash,
- BlockSize=accountInfo.BlockSize,
- Token=accountInfo.Token
- };
- }
- else
- {
- accountName = UserName;
- container = parts[0];
- relativeUrl = String.Join("/", parts.Splice(1));
- }
-
- var client = new CloudFilesClient(accountInfo);
- var objectInfo=client.GetObjectInfo(accountName, container, relativeUrl);
- return objectInfo;
- }
-
- public Task<ContainerInfo> GetContainerInfo(string filePath)
- {
- if (String.IsNullOrWhiteSpace(filePath))
- throw new ArgumentNullException("filePath");
- Contract.EndContractBlock();
-
- var file=new FileInfo(filePath);
- var relativePath = file.AsRelativeTo(RootPath);
-
- string accountName,container;
-
- var parts=relativePath.Split('\\');
-
- var accountInfo = _accountInfo;
- if (relativePath.StartsWith(FolderConstants.OthersFolder))
- {
- accountName = parts[1];
- container = parts[2];
- //Create the root URL for the target account
- var oldName = UserName;
- var absoluteUri = _accountInfo.StorageUri.AbsoluteUri;
- var nameIndex=absoluteUri.IndexOf(oldName, StringComparison.Ordinal);
- var root=absoluteUri.Substring(0, nameIndex);
-
- accountInfo = new AccountInfo
- {
- UserName = accountName,
- AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),
- StorageUri = new Uri(root + accountName),
- BlockHash=accountInfo.BlockHash,
- BlockSize=accountInfo.BlockSize,
- Token=accountInfo.Token
- };
- }
- else
- {
- accountName = UserName;
- container = parts[0];
- }
-
- return Task.Factory.StartNew(() =>
- {
- var client = new CloudFilesClient(accountInfo);
- var containerInfo = client.GetContainerInfo(accountName, container);
- return containerInfo;
- });
- }
- }
-}
+ var removedPaths = statePaths.Where(sp => !selectivePaths.Any(sp.IsAtOrBelow));\r
+\r
+ UnversionSelectivePaths(removedPaths.ToList());\r
+ }\r
+ else\r
+ {\r
+ StatusKeeper.ClearFolderStatus(Account.AccountPath);\r
+ }\r
+ }\r
+\r
+ public void SetSelectivePaths(Uri[] uris,Uri[] added, Uri[] removed)\r
+ {\r
+ //Convert the uris to paths\r
+ //var selectivePaths = UrisToFilePaths(uris);\r
+ \r
+ var selectiveUri = uris.ToList();\r
+ this.Selectives.SetSelectedUris(_accountInfo,selectiveUri);\r
+\r
+ var removedPaths = UrisToFilePaths(removed);\r
+ UnversionSelectivePaths(removedPaths);\r
+\r
+ }\r
+\r
+ /// <summary>\r
+ /// Mark all unselected paths as Unversioned\r
+ /// </summary>\r
+ /// <param name="removed"></param>\r
+ private void UnversionSelectivePaths(List<string> removed)\r
+ {\r
+ if (removed == null)\r
+ return;\r
+\r
+ //Ensure we remove any file state below the deleted folders\r
+ FileState.UnversionPaths(removed);\r
+ }\r
+\r
+\r
+ /// <summary>\r
+ /// Return a list of absolute filepaths from a list of Uris\r
+ /// </summary>\r
+ /// <param name="uris"></param>\r
+ /// <returns></returns>\r
+ public List<string> UrisToFilePaths(IEnumerable<Uri> uris)\r
+ {\r
+ if (uris == null)\r
+ return new List<string>();\r
+\r
+ var own = (from uri in uris\r
+ where uri.ToString().StartsWith(_accountInfo.StorageUri.ToString())\r
+ let relativePath = _accountInfo.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()\r
+ //Trim the account name\r
+ select Path.Combine(RootPath, relativePath.After(_accountInfo.UserName + '\\'))).ToList();\r
+ var others= (from uri in uris\r
+ where !uri.ToString().StartsWith(_accountInfo.StorageUri.ToString())\r
+ let relativePath = _accountInfo.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()\r
+ //Trim the account name\r
+ select Path.Combine(RootPath,"others-shared", relativePath)).ToList();\r
+ return own.Union(others).ToList(); \r
+ }\r
+\r
+\r
+ public ObjectInfo GetObjectInfo(string filePath)\r
+ {\r
+ if (String.IsNullOrWhiteSpace(filePath))\r
+ throw new ArgumentNullException("filePath");\r
+ Contract.EndContractBlock();\r
+\r
+ var file=new FileInfo(filePath);\r
+ string relativeUrl;//=file.AsRelativeUrlTo(this.RootPath);\r
+ var relativePath = file.AsRelativeTo(RootPath);\r
+ \r
+ string accountName,container;\r
+ \r
+ var parts=relativePath.Split('\\');\r
+\r
+ var accountInfo = _accountInfo;\r
+ if (relativePath.StartsWith(FolderConstants.OthersFolder))\r
+ { \r
+ accountName = parts[1];\r
+ container = parts[2];\r
+ relativeUrl = String.Join("/", parts.Splice(3));\r
+ //Create the root URL for the target account\r
+ var oldName = UserName;\r
+ var absoluteUri = _accountInfo.StorageUri.AbsoluteUri;\r
+ var nameIndex=absoluteUri.IndexOf(oldName, StringComparison.Ordinal);\r
+ var root=absoluteUri.Substring(0, nameIndex);\r
+\r
+ accountInfo = new AccountInfo\r
+ {\r
+ UserName = accountName,\r
+ AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),\r
+ StorageUri = new Uri(root + accountName),\r
+ BlockHash=accountInfo.BlockHash,\r
+ BlockSize=accountInfo.BlockSize,\r
+ Token=accountInfo.Token\r
+ };\r
+ }\r
+ else\r
+ {\r
+ accountName = UserName;\r
+ container = parts[0];\r
+ relativeUrl = String.Join("/", parts.Splice(1));\r
+ }\r
+ \r
+ var client = new CloudFilesClient(accountInfo);\r
+ var objectInfo=client.GetObjectInfo(accountName, container, relativeUrl);\r
+ return objectInfo;\r
+ }\r
+ \r
+ public Task<ContainerInfo> GetContainerInfo(string filePath)\r
+ {\r
+ if (String.IsNullOrWhiteSpace(filePath))\r
+ throw new ArgumentNullException("filePath");\r
+ Contract.EndContractBlock();\r
+\r
+ var file=new FileInfo(filePath);\r
+ var relativePath = file.AsRelativeTo(RootPath);\r
+ \r
+ string accountName,container;\r
+ \r
+ var parts=relativePath.Split('\\');\r
+\r
+ var accountInfo = _accountInfo;\r
+ if (relativePath.StartsWith(FolderConstants.OthersFolder))\r
+ { \r
+ accountName = parts[1];\r
+ container = parts[2]; \r
+ //Create the root URL for the target account\r
+ var oldName = UserName;\r
+ var absoluteUri = _accountInfo.StorageUri.AbsoluteUri;\r
+ var nameIndex=absoluteUri.IndexOf(oldName, StringComparison.Ordinal);\r
+ var root=absoluteUri.Substring(0, nameIndex);\r
+\r
+ accountInfo = new AccountInfo\r
+ {\r
+ UserName = accountName,\r
+ AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),\r
+ StorageUri = new Uri(root + accountName),\r
+ BlockHash=accountInfo.BlockHash,\r
+ BlockSize=accountInfo.BlockSize,\r
+ Token=accountInfo.Token\r
+ };\r
+ }\r
+ else\r
+ {\r
+ accountName = UserName;\r
+ container = parts[0]; \r
+ }\r
+\r
+ return Task.Factory.StartNew(() =>\r
+ {\r
+ var client = new CloudFilesClient(accountInfo);\r
+ var containerInfo = client.GetContainerInfo(accountName, container);\r
+ return containerInfo;\r
+ });\r
+ }\r
+ }\r
+}\r