using System.Net.Mail;
using System.Reflection;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Caliburn.Micro;
return;
}
+ //TODO: Possibly add a delay here?
+ if (e.Args.Contains("startup"))
+ {
+ if (Settings.Default.StartupDelay>TimeSpan.Zero)
+ Thread.Sleep(Settings.Default.StartupDelay);
+ }
+
var splashScreen = new SplashScreen("images/logo.png");
splashScreen.Show(true);
{
CompositionContainer container;
- public AppBootstrapper()
- {
- LogManager.GetLog = type => new log4netLogger(type);
- UpgradeSettings();
-
- }
-
- private void UpgradeSettings()
- {
- if (Settings.Default.MustUpgrade)
- {
- Settings.Default.Upgrade();
- Settings.Default.MustUpgrade = false;
- Settings.Default.Save();
- }
- }
-
- /// <summary>
+ public AppBootstrapper()
+ {
+ LogManager.GetLog = type => new log4netLogger(type);
+ UpgradeSettings();
+
+ }
+
+ private void UpgradeSettings()
+ {
+ if (Settings.Default.MustUpgrade)
+ {
+ Settings.Default.Upgrade();
+ Settings.Default.MustUpgrade = false;
+ Settings.Default.Save();
+ }
+ }
+
+ /// <summary>
/// By default, we are configured to use MEF
/// </summary>
protected override void Configure() {
- var catalog = new AggregateCatalog(
- AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
- );
+ var catalog = new AggregateCatalog(
+ AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
+ );
- Type[] types = { typeof(PithosMonitor), typeof(CloudFilesClient) };
- foreach (var type in types)
- {
- catalog.Catalogs.Add(new AssemblyCatalog(type.Assembly));
- }
+ Type[] types = { typeof(PithosMonitor), typeof(CloudFilesClient) };
+ foreach (var type in types)
+ {
+ catalog.Catalogs.Add(new AssemblyCatalog(type.Assembly));
+ }
container = new CompositionContainer(catalog,true);
batch.AddExportedValue<IWindowManager>(new WindowManager());
batch.AddExportedValue<IEventAggregator>(new EventAggregator());
batch.AddExportedValue(container);
- batch.AddExportedValue(catalog);
+ batch.AddExportedValue(catalog);
container.Compose(batch);
-
- ConventionManager.AddElementConvention<MenuItem>(ItemsControl.ItemsSourceProperty, "DataContext", "Click");
- ConventionManager.AddElementConvention<IntegerUpDown>(IntegerUpDown.ValueProperty, "Value", "ValueChanged");
+
+ ConventionManager.AddElementConvention<MenuItem>(ItemsControl.ItemsSourceProperty, "DataContext", "Click");
+ ConventionManager.AddElementConvention<IntegerUpDown>(IntegerUpDown.ValueProperty, "Value", "ValueChanged");
+ ConventionManager.AddElementConvention<BusyIndicator>(BusyIndicator.IsBusyProperty, "IsBusy", "DataContextChanged");
}
protected override object GetInstance(Type serviceType, string key)
}
}
+ public TimeSpan StartupDelay
+ {
+ get { return _settings.StartupDelay; }
+ set
+ {
+ if (value < TimeSpan.Zero)
+ throw new ArgumentOutOfRangeException();
+ _settings.StartupDelay = value;
+ }
+ }
+
+
public bool StartOnSystemStartup
{
get { return _settings.StartOnSystemStartup; }
<extToolkit:IntegerUpDown x:Name="Settings_PollingInterval" HorizontalAlignment="Left" Width="100" Margin="5,0" Watermark="Enter seconds" Minimum="10" />
<TextBlock Text="Hashing Parallelism" Margin="5"/>
<extToolkit:IntegerUpDown x:Name="Settings_HashingParallelism" HorizontalAlignment="Left" Width="100" Margin="5,0" Watermark="Enter number of tasks" Minimum="1" />
+ <TextBlock Text="Startup Delay (minutes)" Margin="5"/>
+ <extToolkit:IntegerUpDown x:Name="StartupDelay" HorizontalAlignment="Left" Width="100" Margin="5,0" Watermark="Enter number of tasks" Minimum="0" />
</StackPanel>
</TabItem>
</TabControl>
}
#endregion
+
+ public int StartupDelay
+ {
+ get { return (int) Settings.StartupDelay.TotalMinutes; }
+ set
+ {
+ if (value<0)
+ throw new ArgumentOutOfRangeException("value","The Startup Delay must be greater or equal to 0");
+ Settings.StartupDelay = TimeSpan.FromMinutes(value);
+ NotifyOfPropertyChange(()=>StartupDelay);
+ }
+ }
#region Commands
public void SelectiveSyncFolders()
{
var monitor = Shell.Monitors[CurrentAccount.AccountName];
- var folders=monitor.GetRootFolders().ToList();
+
- var model = new SelectiveSynchViewModel(folders,_events,CurrentAccount);
+ var model = new SelectiveSynchViewModel(monitor,_events,CurrentAccount);
if (_windowManager.ShowDialog(model) == true)
{
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.1.0.0")]
-[assembly: AssemblyFileVersionAttribute("0.1.20220.2042")]
+[assembly: AssemblyVersion("0.7.0.0")]
+[assembly: AssemblyFileVersionAttribute("0.7.20221.2042")]
this["HashingParallelism"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("00:01:00")]
+ public global::System.TimeSpan StartupDelay {
+ get {
+ return ((global::System.TimeSpan)(this["StartupDelay"]));
+ }
+ set {
+ this["StartupDelay"] = value;
+ }
+ }
}
}
<Setting Name="HashingParallelism" Type="System.Byte" Scope="User">
<Value Profile="(Default)">1</Value>
</Setting>
+ <Setting Name="StartupDelay" Type="System.TimeSpan" Scope="User">
+ <Value Profile="(Default)">00:01:00</Value>
+ </Setting>
</Settings>
</SettingsFile>
\ No newline at end of file
using System.Linq;
using System.Text;
using Caliburn.Micro;
+using Pithos.Core.Agents;
+using Pithos.Interfaces;
namespace Pithos.Client.WPF.SelectiveSynch
{
public class DirectoryRecord : PropertyChangedBase,IEnumerable<DirectoryRecord>
{
- public DirectoryInfo Info { get; set; }
+ private ObjectInfo _objectInfo;
+ public ObjectInfo ObjectInfo
+ {
+ get { return _objectInfo; }
+ set
+ {
+ _objectInfo = value;
+ Uri = value.Uri;
+ }
+ }
+ public Uri Uri { get; set; }
+ //public DirectoryInfo LocalInfo { get; set; }
DirectoryRecord _parent;
public bool Added { get; set; }
public bool Removed { get; set; }
- private bool? _isChecked;
+ private bool? _isChecked=true;
#region IsChecked
/// <summary>
Removed = !(_isChecked??true);
if (updateChildren && _isChecked.HasValue)
- this.Directories.ForEach(c => c.SetIsChecked(_isChecked, true, false));
+ this.Directories.Apply(c => c.SetIsChecked(_isChecked, true, false));
if (updateParent && _parent != null)
_parent.VerifyCheckState();
void VerifyCheckState()
{
bool? state = null;
- for (int i = 0; i < this.Directories.Count; ++i)
+ for (var i = 0; i < this.Directories.Count(); ++i)
{
- bool? current = this.Directories[i].IsChecked;
+ bool? current = this.Directories.ElementAt(i).IsChecked;
if (i == 0)
{
state = current;
public bool IsInitiallySelected { get; private set; }
- readonly Lazy<List<DirectoryRecord>> _directories = new Lazy<List<DirectoryRecord>>();
+ /*readonly Lazy<List<DirectoryRecord>> _directories = new Lazy<List<DirectoryRecord>>();
public List<DirectoryRecord> Directories
{
{
return _directories.Value;
}
+ }*/
+
+ private IEnumerable<DirectoryRecord> _directories=new List<DirectoryRecord>();
+ public IEnumerable<DirectoryRecord> Directories
+ {
+ get { return _directories; }
+ set { _directories = value; }
}
- public DirectoryRecord(string ignorePath)
+ public DirectoryRecord()
{
- _directories = new Lazy<List<DirectoryRecord>>(() =>
+
+/*
+ _directories = new Lazy<List<DirectoryRecord>>(() =>
+ new List<DirectoryRecord>());
+*/
+/*
+ _directories = new Lazy<List<DirectoryRecord>>(() =>
(from directory in Info.EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
where !directory.FullName.StartsWith(ignorePath)
select new DirectoryRecord(ignorePath) { Info = directory }).ToList());
+*/
}
+ private string _displayName;
+ public string DisplayName
+ {
+ get
+ {
+ if (ObjectInfo != null)
+ return ObjectInfo.Name;
+ return _displayName;
+ }
+ set { _displayName = value; }
+ }
+
+ public DirectoryRecord(string rootPath,ObjectInfo info)
+ {
+ var relativePath = info.RelativeUrlToFilePath(info.Account);
+ //LocalInfo = new DirectoryInfo(Path.Combine(rootPath, relativePath));
+ ObjectInfo = info;
+ }
/*
{
public class SelectiveSynchChanges
{
+ public Uri[] Uris { get; set; }
public AccountSettings Account { get; set; }
- public string[] Added { get; set; }
- public string[] Removed { get; set; }
+ public Uri[] Added { get; set; }
+ public Uri[] Removed { get; set; }
}
}
<Window x:Class="Pithos.Client.WPF.SelectiveSynch.SelectiveSynchView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="clr-namespace:Pithos.Client.WPF.SelectiveSynch" Title="Selective Synch" Height="300" Width="300" >
- <Window.Resources>
-
- <Style x:Key="TreeItemStyle" TargetType="TreeViewItem">
- <Setter Property="IsExpanded" Value="True" />
- <Setter Property="IsSelected" Value="{Binding IsInitiallySelected, Mode=OneTime}" />
- <Setter Property="KeyboardNavigation.AcceptsReturn" Value="True" />
- <Setter Property="local:VirtualToggleButton.IsVirtualToggleButton" Value="True" />
- <Setter Property="local:VirtualToggleButton.IsChecked" Value="{Binding IsChecked}" />
- </Style>
-
- <HierarchicalDataTemplate x:Key="CheckboxStyle" DataType="{x:Type local:DirectoryRecord}"
+ xmlns:local="clr-namespace:Pithos.Client.WPF.SelectiveSynch"
+ xmlns:extToolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended"
+ xmlns:Converters="clr-namespace:Pithos.Client.WPF.Converters"
+ Title="Selective Synch" Height="300" Width="300"
+ ShowInTaskbar="true"
+ WindowStartupLocation="CenterScreen"
+ Icon="/Pithos.Client.WPF;component/Images/PithosTaskbar.png"
+ Background="{StaticResource {x:Static SystemColors.ControlBrushKey}}">
+ <Window.Resources>
+ <ResourceDictionary>
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="..\PithosStyles.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+ <Converters:NullToVisibilityConverter x:Key="NullToVisible" />
+ <Style x:Key="TreeItemStyle" TargetType="TreeViewItem">
+ <Setter Property="IsExpanded" Value="True" />
+ <Setter Property="IsSelected" Value="{Binding IsInitiallySelected, Mode=OneTime}" />
+ <Setter Property="KeyboardNavigation.AcceptsReturn" Value="True" />
+ <Setter Property="local:VirtualToggleButton.IsVirtualToggleButton" Value="True" />
+ <Setter Property="local:VirtualToggleButton.IsChecked" Value="{Binding IsChecked}" />
+ </Style>
+ <HierarchicalDataTemplate x:Key="CheckboxStyle" DataType="{x:Type local:DirectoryRecord}"
ItemsSource="{Binding Directories}" >
- <StackPanel Orientation="Horizontal">
- <CheckBox
+ <StackPanel Orientation="Horizontal">
+ <CheckBox
Focusable="False"
IsChecked="{Binding IsChecked}"
VerticalAlignment="Center"
/>
- <ContentPresenter
- Content="{Binding Info.Name, Mode=OneTime}"
+ <ContentPresenter
+ Content="{Binding DisplayName, Mode=OneTime}"
Margin="2,0"
/>
- </StackPanel>
- </HierarchicalDataTemplate>
+ </StackPanel>
+ </HierarchicalDataTemplate>
+
+ </ResourceDictionary>
+
</Window.Resources>
<Grid>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
- <TreeView Grid.Row="0" Name="PithosDirectory"
+ <extToolkit:BusyIndicator Name="IsBusy" Grid.Row="0" BusyContent="Retrieving folders ..." DisplayAfter="0">
+ <TreeView Name="RootNodes"
ItemContainerStyle="{StaticResource TreeItemStyle}"
ItemTemplate="{StaticResource CheckboxStyle}">
- </TreeView>
+ </TreeView>
+ </extToolkit:BusyIndicator>
<StackPanel Grid.Row="1">
<StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Right">
- <Button Name="SaveChanges" Content="OK" Margin="5,5,10,5" />
- <Button Name="RejectChanges" Content="Cancel" Margin="5,5,10,5" />
+ <Button Name="SaveChanges" Content="OK" Margin="5,5,10,5" Style="{StaticResource ButtonStyle}"/>
+ <Button Name="RejectChanges" Content="Cancel" Margin="5,5,10,5" Style="{StaticResource ButtonStyle}"/>
</StackPanel>
</StackPanel>
</Grid>
public partial class SelectiveSynchView : Window
{
public SelectiveSynchView()
- {
+ {
InitializeComponent();
}
}
using System.IO;
using System.Linq;
using System.Text;
+using System.Threading.Tasks;
using Caliburn.Micro;
using Pithos.Client.WPF.Properties;
+using Pithos.Core;
+using Pithos.Core.Agents;
using Pithos.Interfaces;
using Pithos.Network;
{
class SelectiveSynchViewModel:Screen
{
+ private const string DirectoryType = "application/directory";
private IEventAggregator _events ;
- private string _rootPath;
- private string _cachePath;
- public string RootPath
- {
- get { return _rootPath; }
- set
- {
- _rootPath = value;
- _cachePath = Path.Combine(_rootPath, FolderConstants.CacheFolder);
- _pithosDirectory = new ObservableCollection<DirectoryRecord>{
- new DirectoryRecord(_cachePath) {Info = new DirectoryInfo(value)}};
- NotifyOfPropertyChange(() => RootPath);
- NotifyOfPropertyChange(()=>PithosDirectory);
- }
- }
-
private string _title;
public string Title
{
public AccountSettings Account { get; set; }
- private ObservableCollection<DirectoryRecord> _pithosDirectory;
- public ObservableCollection<DirectoryRecord> PithosDirectory
+ private readonly ObservableCollection<DirectoryRecord> _rootNodes=new ObservableCollection<DirectoryRecord>();
+ public ObservableCollection<DirectoryRecord> RootNodes
{
- get { return _pithosDirectory; }
+ get { return _rootNodes; }
}
- private ObservableCollection<DirectoryInfo> _checks;
- public ObservableCollection<DirectoryInfo> Checks
+ private ObservableCollection<ObjectInfo> _checks;
+ private PithosMonitor _monitor;
+ private bool _isBusy=true;
+
+ public ObservableCollection<ObjectInfo> Checks
{
get { return _checks; }
}
public void GetChecks()
{
- var root = PithosDirectory[0];
- _checks = new ObservableCollection<DirectoryInfo>(
+ var root = RootNodes[0];
+ _checks = new ObservableCollection<ObjectInfo>(
from record in root
where record.IsChecked==true
- select record.Info);
+ select record.ObjectInfo);
NotifyOfPropertyChange(() => Checks);
}
- public SelectiveSynchViewModel(IEnumerable<string> folders, IEventAggregator events, AccountSettings account)
+ public SelectiveSynchViewModel(PithosMonitor monitor, IEventAggregator events, AccountSettings account)
{
Account = account;
AccountName = account.AccountName;
Title = account.AccountName;
- RootPath = account.RootPath;
+ _monitor = monitor;
+ _events = events;
+ TaskEx.Run(LoadRootNode);
+ }
+
+ private void LoadRootNode()
+ {
+ var client = _monitor.CloudClient;
+
+ var dirs = from container in client.ListContainers(_monitor.UserName)
+ select new DirectoryRecord
+ {
+ DisplayName = container.Name,
+ Directories = (from dir in client.ListObjects(_monitor.UserName, container.Name, "")
+ where dir.Content_Type == DirectoryType
+ select new DirectoryRecord { DisplayName = dir.Name, ObjectInfo = dir }).ToList()
+ };
+ var ownFolders = dirs.ToList();
+
+ var accounts = client.ListSharingAccounts();
+
+ var accountNodes=from account in client.ListSharingAccounts()
+ select new DirectoryRecord
+ {
+ DisplayName=account.name,
+ Directories=(from container in client.ListContainers(account.name)
+ select new DirectoryRecord
+ {
+ DisplayName=container.Name,
+ Directories=(from folder in client.ListObjects(account.name,container.Name,"")
+ where folder.Content_Type==DirectoryType
+ select new DirectoryRecord{DisplayName=folder.Name,ObjectInfo=folder}).ToList()
+ }).ToList()
+ };
+
+ var othersNode = new DirectoryRecord
+ {
+ DisplayName = "Others",
+ Directories=accountNodes.ToList()
+ };
+
+
+ var rootItem = new DirectoryRecord
+ {
+ DisplayName = AccountName ,
+ Directories = ownFolders.ToList()
+ };
+
+
+ SetInitialSelections(Account);
+
+ Execute.OnUIThread(()=>
+ {
+ this.RootNodes.Add(rootItem);
+ this.RootNodes.Add(othersNode);
+ IsBusy = false;
+ });
+ }
- SetInitialSelections(account);
+ public bool IsBusy
+ {
+ get {
+ return _isBusy;
+ }
+ set {
+ _isBusy = value;
+ NotifyOfPropertyChange(()=>IsBusy);
+ }
}
private void SetInitialSelections(AccountSettings account)
{
var selections = account.SelectiveFolders;
+
if (selections.Count == 0)
return;
- var root = PithosDirectory[0];
- var selects= from record in root
- where selections.Contains(record.Info.FullName)
- select record;
- selects.Apply(record=>record.IsChecked=true);
+
+ var selects = from rootRecord in RootNodes
+ from record in rootRecord
+ where record.ObjectInfo!=null && selections.Contains(record.ObjectInfo.Name)
+ select record;
+
+ selects.Apply(record=>record.IsChecked=true);
}
protected string AccountName { get; set; }
var selections = GetSelectedFolderNames();
SaveSettings(selections);
- var root = PithosDirectory[0];
- var added= (from record in root
- where record.Added
- select record.Info.FullName.ToLower()).ToArray();
- var removed= (from record in root
- where record.Removed
- select record.Info.FullName.ToLower()).ToArray();
-
- _events.Publish(new SelectiveSynchChanges{Account=Account,Added=added,Removed=removed});
+ //RootNodes is an ObservableCollection, it can't be enumerated iterativelly
+
+ var added= (from root in RootNodes
+ from record in root
+ where record.Added && record.Uri != null
+ select record.Uri).ToArray();
+ var removed = (from root in RootNodes
+ from record in root
+ where record.Removed && record.Uri != null
+ select record.Uri).ToArray();
+ var uris = (from root in RootNodes
+ from record in root
+ where record.IsChecked==true && record.Uri != null
+ select record.Uri).ToArray();
+ _events.Publish(new SelectiveSynchChanges{Account=Account,Uris=uris,Added=added,Removed=removed});
private string[] GetSelectedFolderNames()
{
- var root = PithosDirectory[0];
- var selections = from record in root
- where record.IsChecked == true
- select record.Info.FullName;
+
+ var selections = from node in RootNodes
+ from childNode in node
+ where childNode.ObjectInfo != null
+ && childNode.IsChecked == true
+ select node.ObjectInfo.Uri.ToString();
return selections.ToArray();
}
PithosMonitor monitor;
if (_monitors.TryGetValue(accountName, out monitor))
{
- monitor.AddSelectivePaths(message.Added);
- monitor.RemoveSelectivePaths(message.Removed);
+ monitor.SetSelectivePaths(message.Uris,message.Added,message.Removed);
}
<setting name="HashingParallelism" serializeAs="String">
<value>1</value>
</setting>
+ <setting name="StartupDelay" serializeAs="String">
+ <value>00:01:00</value>
+ </setting>
</Pithos.Client.WPF.Properties.Settings>
</userSettings>
<connectionStrings>
public bool ExtensionsActivated { get; set; }
public int PollingInterval { get; set; }
+ public TimeSpan StartupDelay { get; set; }
public byte HashingParallelism { get; set; }
*/\r
#endregion\r
using System.Collections.Concurrent;\r
+using Pithos.Interfaces;\r
\r
namespace Pithos.Core.Agents\r
{\r
\r
queue.AddFromEnumerable(temp);\r
}\r
+\r
+\r
+ public static IEnumerable<ObjectInfo> FilterBelow(this IEnumerable<ObjectInfo> infos,List<Uri> filterUris )\r
+ {\r
+ if (filterUris == null)\r
+ return infos;\r
+ if (filterUris.Count == 0)\r
+ return infos;\r
+ var filteredUris = from info in infos\r
+ where !filterUris.Any(s => info.Uri.ToString()\r
+ .StartsWith(s.ToString()))\r
+ select info;\r
+ return filteredUris;\r
+ }\r
}\r
}\r
\r
try\r
{\r
+ //Wait for any deletions to finish\r
await NetworkAgent.GetDeleteAwaiter();\r
//Get the poll time now. We may miss some deletions but it's better to keep a file that was deleted\r
//than delete a file that was created while we were executing the poll \r
\r
var differencer = _differencer.PostSnapshot(accountInfo, cleanRemotes);\r
\r
- ProcessDeletedFiles(accountInfo, differencer.Deleted, pollTime);\r
+ ProcessDeletedFiles(accountInfo, differencer.Deleted.FilterBelow(SelectiveUris), pollTime);\r
+\r
+ // @@@ NEED To add previous state here as well, To compare with previous hash\r
+\r
+ \r
\r
//Create a list of actions from the remote files\r
- var allActions = ChangesToActions(accountInfo, differencer.Changed)\r
+ var allActions = ChangesToActions(accountInfo, differencer.Changed.FilterBelow(SelectiveUris))\r
.Union(\r
- CreatesToActions(accountInfo, differencer.Created));\r
+ CreatesToActions(accountInfo, differencer.Created.FilterBelow(SelectiveUris)));\r
\r
//And remove those that are already being processed by the agent\r
var distinctActions = allActions\r
}\r
\r
AccountsDifferencer _differencer = new AccountsDifferencer();\r
+ private List<Uri> _selectiveUris=new List<Uri>();\r
\r
/// <summary>\r
/// Deletes local files that are not found in the list of cloud files\r
Directory.CreateDirectory(path);\r
}\r
}\r
+\r
+ public void SetSyncUris(string[] uris)\r
+ {\r
+ var selectiveUris = uris.Select(uri => new Uri(uri));\r
+ SelectiveUris=selectiveUris.ToList();\r
+ }\r
+\r
+ protected List<Uri> SelectiveUris\r
+ {\r
+ get { return _selectiveUris;}\r
+ set { _selectiveUris = value; }\r
+ }\r
}\r
}\r
using System.Threading.Tasks;
using Castle.ActiveRecord;
using Castle.ActiveRecord.Framework;
+using Castle.ActiveRecord.Queries;
+using NHibernate.Criterion;
using Pithos.Core.Agents;
using Pithos.Interfaces;
using Pithos.Network;
throw;
}
}
+
+ public static void RemovePaths(IEnumerable<string> removed)
+ {
+
+ var disjunction = new Disjunction();
+
+ foreach (var path in removed)
+ {
+ disjunction.Add(Restrictions.On<FileState>(s => s.FilePath).IsLike(path, MatchMode.Start));
+ }
+
+
+
+ var query=QueryOver.Of<FileState>().Where(disjunction);
+ var aq = new ProjectionQuery<FileState,Guid>(query.DetachedCriteria,
+ Projections.ProjectionList().Add(Projections.Id()));
+ var ids=aq.Execute();
+ FileState.DeleteAll(ids);
+
+ }
}
[ActiveRecord("Tags")]
StatusKeeper.StartProcessing(_cancellationSource.Token);
IndexLocalFiles();
+ //Extract the URIs from the string collection
+ var settings = Settings.Accounts.First(s => s.AccountName == _accountInfo.UserName);
+ var selectiveUrls=new string[settings.SelectiveFolders.Count];
+ settings.SelectiveFolders.CopyTo(selectiveUrls,0);
+
+ SetSelectivePaths(selectiveUrls,null,null);
+
StartWatcherAgent();
StartNetworkAgent();
StatusKeeper.ChangeRoots(oldPath, newPath);
}
- public void AddSelectivePaths(string[] added)
+ public void SetSelectivePaths(string[] uris,string[] added, string[] removed)
{
- /* FileAgent.SelectivePaths.AddRange(added);
- NetworkAgent.SyncPaths(added);*/
+ //Convert the uris to paths
+ var selectivePaths = (from string selectiveUrl in uris
+ select new Uri(selectiveUrl)
+ .MakeRelativeUri(_accountInfo.StorageUri)
+ .RelativeUriToFilePath());
+
+ FileAgent.SelectivePaths=selectivePaths.ToList();
+ PollAgent.SetSyncUris(uris);
+ RemoveSelectivePaths(removed);
+
}
- public void RemoveSelectivePaths(string[] removed)
+ /// <summary>
+ /// Delete the folders that were removed from synchronization
+ /// </summary>
+ /// <param name="removed"></param>
+ private void RemoveSelectivePaths(IEnumerable<string> removed)
{
- FileAgent.SelectivePaths.RemoveAll(removed.Contains);
+ if (removed == null)
+ return;
+
foreach (var removedPath in removed.Where(Directory.Exists))
{
Directory.Delete(removedPath,true);
}
- }
- public IEnumerable<ObjectInfo> GetRootFolders()
- {
- var dirs = from container in CloudClient.ListContainers(UserName)
- from dir in CloudClient.ListObjects(UserName, container.Name, "")
- where dir.Content_Type=="application/directory"
- select dir;
- return dirs;
+ //Ensure we remove any file state below the deleted folders
+ FileState.RemovePaths(removed);
}
public ObjectInfo GetObjectInfo(string filePath)
bool ExtensionsActivated { get; set; }
int PollingInterval { get; set; }
+ TimeSpan StartupDelay { get; set; }
byte HashingParallelism { get; set; }
void Save();
public Stream Stream { get; set; }
+
+ public Uri StorageUri { get; set; }
+
public string Account { get; set; }
public string Container { get; set; }
+ public Uri Uri
+ {
+ get
+ {
+ var relativeUrl=String.Format("{0}/{1}/{2}",Account, Container,Name);
+ return new Uri(StorageUri,relativeUrl);
+ }
+ }
+
public string ContendDisposition { get; set; }
public string ContentEncoding { get; set; }
Last_Modified = DateTime.MinValue
};
+
+
public string RelativeUrlToFilePath(string currentAccount)
{
if (Name==null)
public string ProxyDomain { get; set; }
public bool ProxyAuthentication { get; set; }
public bool ExtensionsActivated { get; set; }
+ public TimeSpan StartupDelay { get; set; }
public int PollingInterval { get; set; }
public byte HashingParallelism { get; set; }
ProxyAuthentication = other.ProxyAuthentication;
ExtensionsActivated = other.ExtensionsActivated;
PollingInterval = other.PollingInterval;
+ StartupDelay = other.StartupDelay;
}
public virtual void Save()
{
info.Container = container;
info.Account = account;
+ info.StorageUri = this.StorageUrl;
}
if (Log.IsDebugEnabled) Log.DebugFormat("START");
return infos;
foreach (var info in infos)
{
info.Account = account;
+ if (info.Container == null)
+ info.Container = container;
+ info.StorageUri = this.StorageUrl;
}
if (Log.IsDebugEnabled) Log.DebugFormat("END");
return infos;
void UpdateMetadata(ObjectInfo objectInfo);
void UpdateMetadata(ContainerInfo Container);
+ IList<ShareAccountInfo> ListSharingAccounts(DateTime? since=null);
}
return ;
}
+ public IList<ShareAccountInfo> ListSharingAccounts(DateTime? since = new DateTime?())
+ {
+ return default(IList<ShareAccountInfo>);
+ }
+
public IList<ObjectInfo> ListObjects(string account, string container, DateTime? since = null)
{
{
"{9EF0B969-E518-4E46-987F-47570745A589}:_FE8EA18DF1CB49179367FE453762E9B5"
{
- "Name" = "8:GRNet"
+ "Name" = "8:GRNET"
"AlwaysCreate" = "11:FALSE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:Pithos"
- "ProductCode" = "8:{0558EE1F-65D8-4046-BAF8-EA9325EA6DC1}"
- "PackageCode" = "8:{16F5A9E8-D797-4CD0-AC72-FA6C6AAAAE62}"
+ "ProductCode" = "8:{97C4606C-02B7-4E94-900F-D2654110B39B}"
+ "PackageCode" = "8:{07D12433-2FB8-4BCF-839A-02AD31A2C208}"
"UpgradeCode" = "8:{205365D1-28AA-4322-A46C-FCB37502C6EF}"
"AspNetVersion" = "8:4.0.30319.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
- "ProductVersion" = "8:1.0.0"
+ "ProductVersion" = "8:0.7.0"
"Manufacturer" = "8:GRNET"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:http://code.grnet.gr/projects/pithos-ms-client"
{
"{9EF0B969-E518-4E46-987F-47570745A589}:_9ED8CC47C48243A0B5686A7CE582CDA3"
{
- "Name" = "8:GRNet"
+ "Name" = "8:GRNET"
"AlwaysCreate" = "11:FALSE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:Pithos"
- "ProductCode" = "8:{0558EE1F-65D8-4046-BAF8-EA9325EA6DC1}"
- "PackageCode" = "8:{AD4F4E20-3B8F-470F-95FC-E409BC75DA20}"
+ "ProductCode" = "8:{4CB9D42B-6B18-4E6F-9DCE-4D7E57E562C2}"
+ "PackageCode" = "8:{FDC63D9F-C81B-45F7-8C6E-16DB523137E2}"
"UpgradeCode" = "8:{205365D1-28AA-4322-A46C-FCB37502C6EF}"
"AspNetVersion" = "8:4.0.30319.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
- "ProductVersion" = "8:1.0.0"
+ "ProductVersion" = "8:0.7.0"
"Manufacturer" = "8:GRNET"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:http://code.grnet.gr/projects/pithos-ms-client"
public byte HashingParallelism{get; set; }
+ public TimeSpan StartupDelay { get; set; }
+
public void Save()
{
set { _settings.Value.PollingInterval = value; }
}
+ public TimeSpan StartupDelay
+ {
+ get { return _settings.Value.StartupDelay; }
+ set { _settings.Value.StartupDelay = value; }
+ }
+
public byte HashingParallelism
{
get { return _settings.Value.HashingParallelism; }
public int PollingInterval { get; set; }
public byte HashingParallelism { get; set; }
-
+ public TimeSpan StartupDelay { get; set; }
public bool ProxyAuthentication { get; set; }
public void Save()