Added Permissions, Tags
authorPanagiotis Kanavos <pkanavos@gmail.com>
Thu, 3 Nov 2011 21:50:05 +0000 (23:50 +0200)
committerPanagiotis Kanavos <pkanavos@gmail.com>
Thu, 3 Nov 2011 21:50:05 +0000 (23:50 +0200)
Changed all task iterators to Async

24 files changed:
trunk/Libraries/AsyncCtpLibrary.dll [new file with mode: 0644]
trunk/Pithos.Client.WPF/FileProperties/ContainerPropertiesView.xaml
trunk/Pithos.Client.WPF/FileProperties/ContainerPropertiesViewModel.cs
trunk/Pithos.Client.WPF/FileProperties/FilePropertiesView.xaml
trunk/Pithos.Client.WPF/FileProperties/FilePropertiesViewModel.cs
trunk/Pithos.Client.WPF/FileProperties/Permission.cs [new file with mode: 0644]
trunk/Pithos.Client.WPF/FileProperties/Tag.cs [new file with mode: 0644]
trunk/Pithos.Client.WPF/Images/PithosTaskbar.png [new file with mode: 0644]
trunk/Pithos.Client.WPF/Pithos.Client.WPF.csproj
trunk/Pithos.Core.Test/Pithos.Core.Test.csproj
trunk/Pithos.Core/Agents/CloudTransferAction.cs
trunk/Pithos.Core/Agents/FileInfoExtensions.cs
trunk/Pithos.Core/Agents/NetworkAgent.cs
trunk/Pithos.Core/Agents/WorkflowAgent.cs
trunk/Pithos.Core/Pithos.Core.csproj
trunk/Pithos.Core/PithosWorkflow.cs
trunk/Pithos.Interfaces/FileInfoExtensions.cs [new file with mode: 0644]
trunk/Pithos.Interfaces/ObjectInfo.cs
trunk/Pithos.Interfaces/Pithos.Interfaces.csproj
trunk/Pithos.Network.Test/Pithos.Network.Test.csproj
trunk/Pithos.Network/CloudFilesClient.cs
trunk/Pithos.Network/ContainerInfo.cs
trunk/Pithos.Network/Pithos.Network.csproj
trunk/Pithos.Network/RestClient.cs

diff --git a/trunk/Libraries/AsyncCtpLibrary.dll b/trunk/Libraries/AsyncCtpLibrary.dll
new file mode 100644 (file)
index 0000000..6db1c1f
Binary files /dev/null and b/trunk/Libraries/AsyncCtpLibrary.dll differ
index 5e5d039..4b3e5f9 100644 (file)
@@ -1,8 +1,8 @@
 <Window x:Class="Pithos.Client.WPF.FileProperties.ContainerPropertiesView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-        Title="ContainerPropertiesView" Height="300" Width="300"
-        Background="#FFD4D0C8">
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cal="http://www.caliburnproject.org"
+        Title="ContainerPropertiesView" Height="500" Width="300"
+        Background="#FFD4D0C8" Icon="/Pithos.Client.WPF;component/Images/PithosTaskbar.png">
     <Window.Resources>
         <ResourceDictionary>
             <ResourceDictionary.MergedDictionaries>
@@ -15,6 +15,7 @@
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="*"/>
+            <RowDefinition Height="*"/>
             <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
         <Grid Grid.Row="0" Margin="5">
                 <TextBlock x:Name="BlockHash" Text="2345456" Grid.Row="5" Grid.Column="1" Style="{StaticResource ResourceKey=ValueColumnStyle}"/>
             </Grid>
         </GroupBox>
+        <GroupBox Header="Metadata" Grid.Row="2" >
+            <DataGrid ItemsSource="{Binding Tags}" 
+                    AutoGenerateColumns="False" CanUserAddRows="True" >
+                <DataGrid.Columns>
+                    <DataGridTextColumn Binding="{Binding Name}" Header="Name" />
+                    <DataGridTextColumn Binding="{Binding Value}" Header="Value"  />
+                </DataGrid.Columns>
+            </DataGrid>
+        </GroupBox>
+        <GroupBox Header="Policies" Grid.Row="3" >
+            <DataGrid ItemsSource="{Binding Policies}" 
+                    AutoGenerateColumns="False" CanUserAddRows="True" >
+                <DataGrid.Columns>
+                    <DataGridTextColumn Binding="{Binding Name}" Header="Name" />
+                    <DataGridTextColumn Binding="{Binding Value}" Header="Value"  />
+                </DataGrid.Columns>
+            </DataGrid>
+        </GroupBox>
 
-        <StackPanel Orientation="Horizontal" Grid.Row="3" HorizontalAlignment="Right">
+        <StackPanel Orientation="Horizontal" Grid.Row="4" HorizontalAlignment="Right">
             <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}"/>
             <Button Name="ApplyChanges" Content="Apply" Style="{StaticResource ButtonStyle}" />
index fb4a651..a90d2cd 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.ComponentModel.Composition;
 using System.Diagnostics.Contracts;
 using System.Linq;
@@ -68,6 +69,12 @@ namespace Pithos.Client.WPF.FileProperties
             {
                 _container = value;
 
+                Tags.Clear();
+                var tags = from tag in value.Tags
+                           select new Tag(tag.Key, tag.Value);
+                tags.Apply(tag => Tags.Add(tag));                                            
+
+
                 Count = value.Count;
                 ShortSize = value.Bytes.ToByteSize();
                 Size = String.Format("{0} ({1:N0} bytes)", ShortSize, value.Bytes);
@@ -80,7 +87,12 @@ namespace Pithos.Client.WPF.FileProperties
             }
         }
 
-        
+
+        private readonly ObservableCollection<Tag> _tags = new ObservableCollection<Tag>();
+        public ObservableCollection<Tag> Tags
+        {
+            get { return _tags; }
+        }
 
 
         public ContainerPropertiesViewModel(ShellViewModel shell, ContainerInfo container, string localFolderName)
index 50f088d..5d5e7d5 100644 (file)
@@ -2,10 +2,10 @@
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
-             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
-             mc:Ignorable="d" 
-             d:DesignHeight="300" d:DesignWidth="300"
-        Background="#FFD4D0C8" Height="481">
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:cal="http://www.caliburnproject.org"
+        mc:Ignorable="d" 
+             d:DesignHeight="300" d:DesignWidth="300" MaxWidth="500"
+        Background="#FFD4D0C8" Height="481" Icon="/Pithos.Client.WPF;component/Images/PithosTaskbar.png">
     <Window.Resources>
         <ResourceDictionary>
             <ResourceDictionary.MergedDictionaries>
@@ -18,6 +18,7 @@
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="Auto"/>
             <RowDefinition Height="*"/>
+            <RowDefinition Height="*"/>
             <RowDefinition Height="Auto"/>
         </Grid.RowDefinitions>
 
             </Grid>
         </GroupBox>
         <GroupBox Header="Metadata" Grid.Row="2" >
-            <ListView x:Name="GeneralProperties">
-                <ListView.View>
-                    <GridView>
-                        <GridViewColumn  >
-                            <GridViewColumn.CellTemplate>
+                <DataGrid ItemsSource="{Binding Tags}" 
+                    AutoGenerateColumns="False" CanUserAddRows="True" >
+                    <DataGrid.Columns>                        
+                        <DataGridTemplateColumn >
+                            <DataGridTemplateColumn.CellTemplate>
+                                <DataTemplate>
+                                    <Button Content=" - " 
+                                cal:Message.Attach="RemoveTag($dataContext)" />
+                                </DataTemplate>
+                            </DataGridTemplateColumn.CellTemplate>
+                        </DataGridTemplateColumn>
+                        <DataGridTextColumn Binding="{Binding Name}" Header="Name" />
+                        <DataGridTextColumn Binding="{Binding Value}" Header="Value"  />                    
+                    </DataGrid.Columns>
+                </DataGrid>
+        </GroupBox>
+        <GroupBox Header="Permissions" Grid.Row="3" >
+                <DataGrid ItemsSource="{Binding Permissions}" 
+                    AutoGenerateColumns="False" CanUserAddRows="True">
+                    <DataGrid.Columns>
+                        <DataGridTemplateColumn >
+                            <DataGridTemplateColumn.CellTemplate>
                                 <DataTemplate>
-                                    <Button Content="-" Width="20"/>
+                                    <Button Content=" - " 
+                                cal:Message.Attach="RemoveTag($dataContext)" />
                                 </DataTemplate>
-                            </GridViewColumn.CellTemplate>
-                        </GridViewColumn>
-                        <GridViewColumn Header="Name"/>
-                        <GridViewColumn Header="Value" />                
-                </GridView>
-            </ListView.View>
-                <ListViewItem Content="Moo">                                        
-                </ListViewItem>
-            </ListView>
+                            </DataGridTemplateColumn.CellTemplate>
+                        </DataGridTemplateColumn>
+                        <DataGridTextColumn Binding="{Binding UserName}" Header="Name" />
+                        <DataGridCheckBoxColumn Binding="{Binding Read}" Header="Read"/>
+                        <DataGridCheckBoxColumn Binding="{Binding Write}" Header="Write"/>                                           
+                    </DataGrid.Columns>
+                </DataGrid>
         </GroupBox>
-        <StackPanel Orientation="Horizontal" Grid.Row="3" HorizontalAlignment="Right">
+        <StackPanel Orientation="Horizontal" Grid.Row="4" HorizontalAlignment="Right">
             <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}"/>
             <Button Name="ApplyChanges" Content="Apply" Style="{StaticResource ButtonStyle}" />
index cf40563..64654c2 100644 (file)
@@ -82,9 +82,17 @@ namespace Pithos.Client.WPF
             {
                 _pithosFile = value;
                 
-                if (Permissions!=null)
-                    ((IDictionary<string,string>)Permissions).Clear();                
-                value.Permissions.Apply(perm=>Permissions.Add(perm.Key,perm.Value));
+                Permissions.Clear();
+                Tags.Clear();
+
+                var perms=from permission in value.Permissions
+                            select new Permission(permission.Key, permission.Value);
+                perms.Apply(perm=>Permissions.Add(perm));
+                
+                var tags=from tag in value.Tags
+                             select new Tag(tag.Key, tag.Value);
+                tags.Apply(tag=>Tags.Add(tag));                                            
+
                 Kind=value.Content_Type;
                 ShortSize = value.Bytes.ToByteSize();
                 Size = String.Format("{0} ({1:N0} bytes)", ShortSize, value.Bytes);
@@ -103,19 +111,20 @@ namespace Pithos.Client.WPF
                 NotifyOfPropertyChange(()=>PithosFile);
             }
         }
-        
 
 
-        private ObservableConcurrentDictionary<string, string> _permissions;
-        public ObservableConcurrentDictionary<string, string> Permissions
+
+        private readonly ObservableCollection<Tag> _tags = new ObservableCollection<Tag>();
+        public ObservableCollection<Tag> Tags
         {
-            get { return _permissions; }
-            set
-            {
-                _permissions = value;
-            }
+            get { return _tags; }
         }
 
+        private readonly ObservableCollection<Permission> _permissions = new ObservableCollection<Permission>();
+        public ObservableCollection<Permission> Permissions
+        {
+            get { return _permissions; }
+        }
 
         public void Refresh()
         {
diff --git a/trunk/Pithos.Client.WPF/FileProperties/Permission.cs b/trunk/Pithos.Client.WPF/FileProperties/Permission.cs
new file mode 100644 (file)
index 0000000..723a06f
--- /dev/null
@@ -0,0 +1,58 @@
+using Caliburn.Micro;
+
+namespace Pithos.Client.WPF
+{
+    public class Permission:PropertyChangedBase
+    {
+        private string _userName;
+        public string UserName
+        {
+            get { return _userName; }
+            set
+            {
+                _userName = value;
+                NotifyOfPropertyChange(()=>UserName);
+            }
+        }
+
+        private bool _read;
+        public bool Read
+        {
+            get { return _read; }
+            set
+            {
+                _read = value;
+                if (_read)
+                    Write = false;
+                NotifyOfPropertyChange(()=>Read);
+            }
+        }
+
+        private bool _write;
+
+        public bool Write
+        {
+            get { return _write; }
+            set
+            {
+                _write = value;
+                if (_write)
+                    Read = false;
+                NotifyOfPropertyChange(()=>Write);
+            }
+        }
+
+        public Permission(string userName, string permission)
+        {
+            UserName = userName;
+            Read = (string.Compare(permission, "read", true) == 0);
+            Write= (string.Compare(permission, "write", true) == 0);
+        }
+
+        public Permission()
+        {
+            
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/trunk/Pithos.Client.WPF/FileProperties/Tag.cs b/trunk/Pithos.Client.WPF/FileProperties/Tag.cs
new file mode 100644 (file)
index 0000000..344049b
--- /dev/null
@@ -0,0 +1,42 @@
+using Caliburn.Micro;
+
+namespace Pithos.Client.WPF
+{
+    public class Tag:PropertyChangedBase
+    {
+        private string _name;
+        public string Name
+        {
+            get { return _name; }
+            set
+            {
+                _name = value;
+                NotifyOfPropertyChange(()=>Name);
+            }
+        }
+
+        private string _value;
+        public string Value
+        {
+            get { return _value; }
+            set
+            {
+                _value = value;
+                NotifyOfPropertyChange(()=>Value);
+            }
+        }
+
+        public Tag(string name, string value)
+        {
+            Name = name;
+            Value = value;
+        }
+
+        public Tag()
+        {
+            
+        }
+
+
+    }
+}
\ No newline at end of file
diff --git a/trunk/Pithos.Client.WPF/Images/PithosTaskbar.png b/trunk/Pithos.Client.WPF/Images/PithosTaskbar.png
new file mode 100644 (file)
index 0000000..dfc149c
Binary files /dev/null and b/trunk/Pithos.Client.WPF/Images/PithosTaskbar.png differ
index 12e7dd3..b506878 100644 (file)
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="AsyncCtpLibrary, Version=1.0.4107.18181, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>C:\Users\Administrator\Documents\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary.dll</HintPath>
+    <Reference Include="AsyncCtpLibrary">
+      <HintPath>..\Libraries\AsyncCtpLibrary.dll</HintPath>
     </Reference>
     <Reference Include="Caliburn.Micro, Version=1.2.0.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
       <HintPath>..\Libraries\Caliburn.Micro.dll</HintPath>
       <DependentUpon>FilePropertiesView.xaml</DependentUpon>
     </Compile>
     <Compile Include="FileProperties\FilePropertiesViewModel.cs" />
+    <Compile Include="FileProperties\Permission.cs" />
     <Compile Include="FileProperties\SizeExtensions.cs" />
+    <Compile Include="FileProperties\Tag.cs" />
     <Compile Include="NativeMethods.cs" />
     <Compile Include="Notification.cs" />
     <Compile Include="PithosAccount.cs" />
   <ItemGroup>
     <Resource Include="Images\Container.png" />
   </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\PithosTaskbar.png" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
index 51122e9..523b332 100644 (file)
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="AsyncCtpLibrary, Version=1.0.4107.18181, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
-      <HintPath>C:\Users\Administrator\Documents\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary.dll</HintPath>
+    <Reference Include="AsyncCtpLibrary">
+      <HintPath>..\Libraries\AsyncCtpLibrary.dll</HintPath>
     </Reference>
     <Reference Include="Castle.ActiveRecord, Version=3.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL" />
     <Reference Include="Castle.Core">
index 3e7999f..d9f8637 100644 (file)
@@ -73,6 +73,11 @@ namespace Pithos.Core.Agents
             var filePath = CloudFile.RelativeUrlToFilePath(AccountInfo.UserName);
             return Path.Combine(AccountInfo.AccountPath, filePath);
         }
+
+        public override string ToString()
+        {
+            return String.Format("{0}:{1}->{2}", this.Action, this.LocalFile.FullName, this.CloudFile.Name);
+        }
     }    
 
     public class CloudDownloadAction:CloudAction
@@ -80,14 +85,29 @@ namespace Pithos.Core.Agents
         public CloudDownloadAction(AccountInfo accountInfo, ObjectInfo cloudFile)
             :base(accountInfo,CloudActionType.DownloadUnconditional)
         {            
+            if (String.IsNullOrWhiteSpace(cloudFile.Container))
+                throw new ArgumentException("CloudFile.Container","cloudFile");
+            Contract.EndContractBlock();
+
             CloudFile = cloudFile;
         }
+
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
+        }
+
+        public override string ToString()
+        {
+            return String.Format("{0}: _ <- {1}", this.Action, this.CloudFile.Name);
+        }
         
     }
     public class CloudDeleteAction:CloudAction
     {
-        public CloudDeleteAction(AccountInfo accountInfo, string fileName, FileState fileState)
-            : this(accountInfo,new ObjectInfo { Name = fileName },fileState)
+        public CloudDeleteAction(AccountInfo accountInfo,FileInfo fileInfo, FileState fileState)
+            : this(accountInfo,new ObjectInfo(accountInfo.AccountPath,accountInfo.UserName,fileInfo),fileState)
         {
         }
 
@@ -101,42 +121,59 @@ namespace Pithos.Core.Agents
         public CloudDeleteAction(CloudAction action)
             : this(action.AccountInfo,action.CloudFile,action.FileState)
         {}
+
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
+        }
+
+        public override string ToString()
+        {
+            return String.Format("{0}: _ ->{1}", this.Action, this.CloudFile.Name);
+        }
+
     }
 
     public class CloudUploadAction:CloudAction
     {
-        public CloudUploadAction(AccountInfo accountInfo, FileInfo fileInfo, FileState state, int blockSize, string algorithm) 
-            : base(accountInfo,CloudActionType.UploadUnconditional,fileInfo,ObjectInfo.Empty,state,blockSize,algorithm)
+        public CloudUploadAction(AccountInfo accountInfo, FileInfo fileInfo, FileState state, int blockSize, string algorithm)
+            : base(accountInfo, CloudActionType.UploadUnconditional, fileInfo, 
+            new ObjectInfo(accountInfo.AccountPath, accountInfo.UserName,fileInfo), state, blockSize, algorithm)
         {
-            var relativeUrl = fileInfo.AsRelativeUrlTo(accountInfo.AccountPath);
-            //The first part of the URL is the container
-            var slashIndex = relativeUrl.IndexOf('/');
-            var container = relativeUrl.Substring(0, slashIndex);
-            //The second is the file's url relative to the container
-            var fileUrl = relativeUrl.Substring(slashIndex + 1);
+        }
 
-            CloudFile = new ObjectInfo {Account = accountInfo.UserName, Container = container, Name = fileUrl};            
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
         }
+
     }
 
     public class CloudMoveAction:CloudAction
     {
-        public string OldFileName { get; set; }
-        public string OldPath { get; set; }
-        public string NewFileName { get; set; }
-        public string NewPath { get; set; }
+        public ObjectInfo OldCloudFile { get; set; }
+
+        public FileInfo OldLocalFile { get; set; }
 
-        public CloudMoveAction(AccountInfo accountInfo, CloudActionType action, string oldPath, string oldFileName, string newFileName, string newPath)
+        public CloudMoveAction(AccountInfo accountInfo, CloudActionType action, FileInfo oldFile, FileInfo newFile)
             :base(accountInfo,action)
         {
-            OldFileName = oldFileName;
-            OldPath = oldPath;
-            NewFileName = newFileName;
-            NewPath = newPath;
+            LocalFile = newFile;
+            CloudFile = new ObjectInfo(accountInfo.AccountPath, accountInfo.UserName, newFile);
+            
+            OldLocalFile = oldFile;
+            OldCloudFile = new ObjectInfo(accountInfo.AccountPath, accountInfo.UserName, oldFile);
+
             //This is a rename operation, a hash will not be used
             LocalHash = new Lazy<string>(() => String.Empty, LazyThreadSafetyMode.ExecutionAndPublication);
         }
 
+        public override string ToString()
+        {
+            return String.Format("{0}:{1}->{2}", this.Action, OldCloudFile.Name, CloudFile.Name);
+        }
 
     }
 
index 99895c3..f9af7e6 100644 (file)
@@ -12,46 +12,7 @@ namespace Pithos.Core.Agents
 {
     static class FileInfoExtensions
     {
-        public static  string AsRelativeTo(this FileInfo fileInfo,string path )
-        {
-            if (String.IsNullOrWhiteSpace(path))
-                throw new ArgumentNullException("path");            
-            Contract.EndContractBlock();
-            
-
-            if (!path.EndsWith("\\"))
-                path=path.ToLower() + "\\";
-            int pathLength = path.Length;            
-            
-            var filePath = fileInfo.FullName;
-
-            if (!filePath.StartsWith(path,StringComparison.InvariantCultureIgnoreCase))
-                throw new ArgumentException(String.Format("The path {0} doesn't contain the file {1}",path,filePath));
-            
-            var relativePath = filePath.Substring(pathLength, filePath.Length - pathLength);
-
-            return relativePath;
-        }
-
-        public static string AsRelativeUrlTo(this FileInfo fileInfo,string path )
-        {
-            if (String.IsNullOrWhiteSpace(path))
-                throw new ArgumentNullException("path");
-            Contract.EndContractBlock();
-
-            var relativePath = fileInfo.AsRelativeTo(path);
-            var replacedSlashes = relativePath.Replace("\\","/");
-            var escaped = Uri.EscapeUriString(replacedSlashes);
-            return escaped;
-        }
-
-        public static string RelativeUriToFilePath(this Uri uri)
-        {
-            var unescaped = Uri.UnescapeDataString(uri.ToString());
-            var path = unescaped.Replace("/", "\\");
-            return path;
-        }
-
+        
 
         public static int Read(this FileInfo fileInfo,byte[] buffer,int offset,int count)
         {            
index 3b14b0f..94751e0 100644 (file)
@@ -66,7 +66,7 @@ namespace Pithos.Core.Agents
             });
         }
 
-        private Task<object> Process(CloudAction action)
+        private async Task Process(CloudAction action)
         {
             if (action == null)
                 throw new ArgumentNullException("action");
@@ -78,8 +78,7 @@ namespace Pithos.Core.Agents
 
             using (log4net.ThreadContext.Stacks["NETWORK"].Push("PROCESS"))
             {                
-                Log.InfoFormat("[ACTION] Start Processing {0}:{1}->{2}", action.Action, action.LocalFile,
-                               action.CloudFile.Name);
+                Log.InfoFormat("[ACTION] Start Processing {0}", action);
 
                 var localFile = action.LocalFile;
                 var cloudFile = action.CloudFile;
@@ -91,28 +90,28 @@ namespace Pithos.Core.Agents
                     switch (action.Action)
                     {
                         case CloudActionType.UploadUnconditional:
-                            UploadCloudFile(action);
+                            await UploadCloudFile(action);
                             break;
                         case CloudActionType.DownloadUnconditional:
 
-                            DownloadCloudFile(accountInfo,  cloudFile,downloadPath);
+                            await DownloadCloudFile(accountInfo,  cloudFile,downloadPath);
                             break;
                         case CloudActionType.DeleteCloud:
                             DeleteCloudFile(accountInfo, cloudFile, cloudFile.Name);
                             break;
                         case CloudActionType.RenameCloud:
                             var moveAction = (CloudMoveAction)action;
-                            RenameCloudFile(accountInfo, cloudFile, moveAction);
+                            RenameCloudFile(accountInfo, moveAction);
                             break;
                         case CloudActionType.MustSynch:
 
                             if (!File.Exists(downloadPath))
                             {                                
-                                DownloadCloudFile(accountInfo, cloudFile, downloadPath);
+                                await DownloadCloudFile(accountInfo, cloudFile, downloadPath);
                             }
                             else
                             {
-                                SyncFiles(accountInfo, action);
+                                await SyncFiles(accountInfo, action);
                             }
                             break;
                     }
@@ -136,12 +135,11 @@ namespace Pithos.Core.Agents
                                      action.Action, action.LocalFile, action.CloudFile, exc);
 
                     _agent.Post(action);
-                }
-                return CompletedTask<object>.Default;
+                }                
             }
         }
 
-        private void SyncFiles(AccountInfo accountInfo,CloudAction action)
+        private async Task SyncFiles(AccountInfo accountInfo,CloudAction action)
         {
             if (accountInfo == null)
                 throw new ArgumentNullException("accountInfo");
@@ -191,7 +189,7 @@ namespace Pithos.Core.Agents
                 {
                     case FileStatus.Unchanged:                        
                         //If the local file's status is Unchanged, we can go on and download the newer cloud file
-                        DownloadCloudFile(accountInfo,cloudFile,downloadPath);
+                        await DownloadCloudFile(accountInfo,cloudFile,downloadPath);
                         break;
                     case FileStatus.Modified:
                         //If the local file is Modified, we may have a conflict. In this case we should mark the file as Conflict
@@ -487,30 +485,36 @@ namespace Pithos.Core.Agents
         }
 
 
-        private void RenameCloudFile(AccountInfo accountInfo,ObjectInfo cloudFile,CloudMoveAction action)
+        private void RenameCloudFile(AccountInfo accountInfo,CloudMoveAction action)
         {
             if (accountInfo==null)
                 throw new ArgumentNullException("accountInfo");
-            if (cloudFile==null)
-                throw new ArgumentNullException("cloudFile");
             if (action==null)
                 throw new ArgumentNullException("action");
-            if (String.IsNullOrWhiteSpace(action.CloudFile.Container))
-                throw new ArgumentException("Invalid container", "action");
+            if (action.CloudFile==null)
+                throw new ArgumentException("CloudFile","action");
+            if (action.LocalFile==null)
+                throw new ArgumentException("LocalFile","action");
+            if (action.OldLocalFile==null)
+                throw new ArgumentException("OldLocalFile","action");
+            if (action.OldCloudFile==null)
+                throw new ArgumentException("OldCloudFile","action");
             Contract.EndContractBlock();
+            
+            var newFilePath = action.LocalFile.FullName;            
             //The local file is already renamed
-            this.StatusKeeper.SetFileOverlayStatus(action.NewPath, FileOverlayStatus.Modified);
+            this.StatusKeeper.SetFileOverlayStatus(newFilePath, FileOverlayStatus.Modified);
 
 
             var account = action.CloudFile.Account ?? accountInfo.UserName;
-            var container = action.CloudFile.Container;// ?? FolderConstants.PithosContainer;
+            var container = action.CloudFile.Container;
             
             var client = new CloudFilesClient(accountInfo);
-            client.MoveObject(account, container, action.OldFileName, container, action.NewFileName);
+            client.MoveObject(account, container, action.OldCloudFile.Name, container, action.CloudFile.Name);
 
-            this.StatusKeeper.SetFileStatus(action.NewPath, FileStatus.Unchanged);
-            this.StatusKeeper.SetFileOverlayStatus(action.NewPath, FileOverlayStatus.Normal);
-            NativeMethods.RaiseChangeNotification(action.NewPath);
+            this.StatusKeeper.SetFileStatus(newFilePath, FileStatus.Unchanged);
+            this.StatusKeeper.SetFileOverlayStatus(newFilePath, FileOverlayStatus.Normal);
+            NativeMethods.RaiseChangeNotification(newFilePath);
         }
 
         private void DeleteCloudFile(AccountInfo accountInfo, ObjectInfo cloudFile,string fileName)
@@ -547,7 +551,7 @@ namespace Pithos.Core.Agents
         }
 
         //Download a file.
-        private void DownloadCloudFile(AccountInfo accountInfo, ObjectInfo cloudFile , string localPath)
+        private async Task DownloadCloudFile(AccountInfo accountInfo, ObjectInfo cloudFile , string localPath)
         {
             if (accountInfo == null)
                 throw new ArgumentNullException("accountInfo");
@@ -562,38 +566,18 @@ namespace Pithos.Core.Agents
             if (!Path.IsPathRooted(localPath))
                 throw new ArgumentException("The localPath must be rooted", "localPath");
             Contract.EndContractBlock();
-            
-            var download=Task.Factory.Iterate(DownloadIterator(accountInfo,cloudFile, localPath));
-            download.Wait();
-        }
-
-        private IEnumerable<Task> DownloadIterator(AccountInfo accountInfo,ObjectInfo cloudFile, string localPath)
-        {
-            if (accountInfo == null)
-                throw new ArgumentNullException("accountInfo");
-            if (cloudFile == null)
-                throw new ArgumentNullException("cloudFile");
-            if (String.IsNullOrWhiteSpace(cloudFile.Account))
-                throw new ArgumentNullException("cloudFile");
-            if (String.IsNullOrWhiteSpace(cloudFile.Container))
-                throw new ArgumentNullException("cloudFile");
-            if (String.IsNullOrWhiteSpace(localPath))
-                throw new ArgumentNullException("localPath");
-            if (!Path.IsPathRooted(localPath))
-                throw new ArgumentException("The localPath must be rooted", "localPath");
-            Contract.EndContractBlock();
-
+                       
             Uri relativeUrl = new Uri(cloudFile.Name, UriKind.Relative);
 
             var url = relativeUrl.ToString();
             if (cloudFile.Name.EndsWith(".ignore", StringComparison.InvariantCultureIgnoreCase))
-                yield break;
+                return;
 
             //Are we already downloading or uploading the file? 
             using (var gate=NetworkGate.Acquire(localPath, NetworkOperation.Downloading))
             {
                 if (gate.Failed)
-                    yield break;
+                    return;
                 //The file's hashmap will be stored in the same location with the extension .hashmap
                 //var hashPath = Path.Combine(FileAgent.CachePath, relativePath + ".hashmap");
                 
@@ -602,18 +586,14 @@ namespace Pithos.Core.Agents
                 var container = cloudFile.Container;
 
                 //Retrieve the hashmap from the server
-                var getHashMap = client.GetHashMap(account, container, url);
-                yield return getHashMap;
-                
-                var serverHash=getHashMap.Result;
+                var serverHash = await client.GetHashMap(account, container, url);
                 //If it's a small file
-                var downloadTask=(serverHash.Hashes.Count == 1 )
+                if (serverHash.Hashes.Count == 1 )
                     //Download it in one go
-                    ? DownloadEntireFile(accountInfo,client, cloudFile, relativeUrl, localPath, serverHash) 
+                    await DownloadEntireFile(accountInfo, client, cloudFile, relativeUrl, localPath, serverHash);
                     //Otherwise download it block by block
-                    : DownloadWithBlocks(accountInfo,client, cloudFile, relativeUrl, localPath, serverHash);
-
-                yield return downloadTask;
+                else
+                    await DownloadWithBlocks(accountInfo,client, cloudFile, relativeUrl, localPath, serverHash);                
 
                 if (cloudFile.AllowedTo == "read")
                 {
@@ -628,7 +608,7 @@ namespace Pithos.Core.Agents
         }
 
         //Download a small file with a single GET operation
-        private Task DownloadEntireFile(AccountInfo accountInfo, CloudFilesClient client, ObjectInfo cloudFile, Uri relativeUrl, string localPath,TreeHash serverHash)
+        private async Task DownloadEntireFile(AccountInfo accountInfo, CloudFilesClient client, ObjectInfo cloudFile, Uri relativeUrl, string localPath,TreeHash serverHash)
         {
             if (client == null)
                 throw new ArgumentNullException("client");
@@ -649,12 +629,12 @@ namespace Pithos.Core.Agents
                 var localMD5 = Signature.CalculateMD5(localPath);
                 var cloudHash=serverHash.TopHash.ToHashString();
                 if (localMD5==cloudHash)
-                    return CompletedTask.Default;
+                    return;
                 //Then check with a treehash
                 var localTreeHash = Signature.CalculateTreeHash(localPath, serverHash.BlockSize, serverHash.BlockHash);
                 var localHash = localTreeHash.TopHash.ToHashString();
                 if (localHash==cloudHash)
-                    return CompletedTask.Default;
+                    return;
             }
 
             var fileAgent = GetFileAgent(accountInfo);
@@ -668,7 +648,7 @@ namespace Pithos.Core.Agents
                 Directory.CreateDirectory(tempFolder);
 
             //Download the object to the temporary location
-            var getObject = client.GetObject(cloudFile.Account, cloudFile.Container, relativeUrl.ToString(), tempPath).ContinueWith(t =>
+            await client.GetObject(cloudFile.Account, cloudFile.Container, relativeUrl.ToString(), tempPath).ContinueWith(t =>
             {
                 t.PropagateExceptions();
                 //Create the local folder if it doesn't exist (necessary for shared objects)
@@ -683,12 +663,11 @@ namespace Pithos.Core.Agents
                 //Notify listeners that a local file has changed
                 StatusNotification.NotifyChangedFile(localPath);
 
-            });
-            return getObject;
+            });            
         }
 
         //Download a file asynchronously using blocks
-        public Task DownloadWithBlocks(AccountInfo accountInfo, CloudFilesClient client, ObjectInfo cloudFile, Uri relativeUrl, string localPath, TreeHash serverHash)
+        public async Task DownloadWithBlocks(AccountInfo accountInfo, CloudFilesClient client, ObjectInfo cloudFile, Uri relativeUrl, string localPath, TreeHash serverHash)
         {
             if (client == null)
                 throw new ArgumentNullException("client");
@@ -704,26 +683,7 @@ namespace Pithos.Core.Agents
                 throw new ArgumentNullException("serverHash");
             Contract.EndContractBlock();
             
-            return Task.Factory.Iterate(BlockDownloadIterator(accountInfo,client,cloudFile, relativeUrl, localPath, serverHash));
-        }
-
-        private IEnumerable<Task> BlockDownloadIterator(AccountInfo accountInfo,CloudFilesClient client,  ObjectInfo cloudFile, Uri relativeUrl, string localPath, TreeHash serverHash)
-        {
-            if (client == null)
-                throw new ArgumentNullException("client");
-            if (cloudFile==null)
-                throw new ArgumentNullException("cloudFile");
-            if (relativeUrl == null)
-                throw new ArgumentNullException("relativeUrl");
-            if (String.IsNullOrWhiteSpace(localPath))
-                throw new ArgumentNullException("localPath");
-            if (!Path.IsPathRooted(localPath))
-                throw new ArgumentException("The localPath must be rooted", "localPath");
-            if(serverHash==null)
-                throw new ArgumentNullException("serverHash");
-            Contract.EndContractBlock();
-            
-            var fileAgent = GetFileAgent(accountInfo);
+           var fileAgent = GetFileAgent(accountInfo);
             
             //Calculate the relative file path for the new file
             var relativePath = relativeUrl.RelativeUriToFilePath();
@@ -732,9 +692,7 @@ namespace Pithos.Core.Agents
             
                         
             //Calculate the file's treehash
-            var calcHash = Signature.CalculateTreeHashAsync(localPath, serverHash.BlockSize,serverHash.BlockHash);
-            yield return calcHash;                        
-            var treeHash = calcHash.Result;
+            var treeHash = await Signature.CalculateTreeHashAsync(localPath, serverHash.BlockSize, serverHash.BlockHash);
                 
             //And compare it with the server's hash
             var upHashes = serverHash.GetHashesAsStrings();
@@ -758,12 +716,10 @@ namespace Pithos.Core.Agents
                         end= ((i + 1)*serverHash.BlockSize) ;
                             
                     //Download the missing block
-                    var getBlock = client.GetBlock(cloudFile.Account, cloudFile.Container, relativeUrl, start, end);
-                    yield return getBlock;
-                    var block = getBlock.Result;
+                    var block = await client.GetBlock(cloudFile.Account, cloudFile.Container, relativeUrl, start, end);
 
                     //and store it
-                    yield return blockUpdater.StoreBlock(i, block);
+                    blockUpdater.StoreBlock(i, block);
 
 
                     Log.InfoFormat("[BLOCK GET] FINISH {0} of {1} for {2}", i, upHashes.Length, localPath);
@@ -782,7 +738,7 @@ namespace Pithos.Core.Agents
         }
 
 
-        private async void UploadCloudFile(CloudAction action)
+        private async Task UploadCloudFile(CloudAction action)
         {
             if (action == null)
                 throw new ArgumentNullException("action");           
@@ -864,7 +820,7 @@ namespace Pithos.Core.Agents
                     var treeHash = await Signature.CalculateTreeHashAsync(fileInfo.FullName, accountInfo.BlockSize,
                         accountInfo.BlockHash);                
                     
-                    UploadWithHashMap(accountInfo,cloudFile,fileInfo,cloudFile.Name,treeHash);
+                    await UploadWithHashMap(accountInfo,cloudFile,fileInfo,cloudFile.Name,treeHash);
 
                     //If everything succeeds, change the file and overlay status to normal
                     this.StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal);
@@ -894,7 +850,7 @@ namespace Pithos.Core.Agents
 
         }
 
-        public async void UploadWithHashMap(AccountInfo accountInfo,ObjectInfo cloudFile,FileInfo fileInfo,string url,TreeHash treeHash)
+        public async Task UploadWithHashMap(AccountInfo accountInfo,ObjectInfo cloudFile,FileInfo fileInfo,string url,TreeHash treeHash)
         {
             if (accountInfo == null)
                 throw new ArgumentNullException("accountInfo");
@@ -913,7 +869,7 @@ namespace Pithos.Core.Agents
             var fullFileName = fileInfo.FullName;
 
             var account = cloudFile.Account ?? accountInfo.UserName;
-            var container = cloudFile.Container ;//?? FolderConstants.PithosContainer;
+            var container = cloudFile.Container ;
 
             var client = new CloudFilesClient(accountInfo);
             //Send the hashmap to the server            
index 1580b28..7b00a2f 100644 (file)
@@ -80,13 +80,12 @@ namespace Pithos.Core.Agents
                         NetworkAgent.Post(new CloudUploadAction(accountInfo,info, fileState, accountInfo.BlockSize,
                             accountInfo.BlockHash));
                         break;
-                    case FileStatus.Deleted:
-                        string fileName = info.AsRelativeUrlTo(accountInfo.AccountPath);
-                        NetworkAgent.Post(new CloudDeleteAction(accountInfo,fileName, fileState));
+                    case FileStatus.Deleted:                       
+                        NetworkAgent.Post(new CloudDeleteAction(accountInfo,info, fileState));
                         break;
                     case FileStatus.Renamed:
-                        NetworkAgent.Post(new CloudMoveAction(accountInfo,CloudActionType.RenameCloud, state.OldFileName,
-                                                              state.OldPath, state.FileName, state.Path));
+                        NetworkAgent.Post(new CloudMoveAction(accountInfo,CloudActionType.RenameCloud, new FileInfo(state.OldPath),
+                                                              new FileInfo(state.Path)));
                         break;
                 }
 
index af7c2b3..5f72b4e 100644 (file)
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="AsyncCtpLibrary">
-      <HintPath>C:\Users\Administrator\Documents\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary.dll</HintPath>
+      <HintPath>..\Libraries\AsyncCtpLibrary.dll</HintPath>
     </Reference>
     <Reference Include="Caliburn.Micro, Version=1.2.0.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
       <HintPath>..\Libraries\Caliburn.Micro.dll</HintPath>
index 4bcde1e..44e9f60 100644 (file)
@@ -48,8 +48,6 @@ namespace Pithos.Core
                     if (status == FileStatus.Created)
                         return oldStatus;
                     break;
-                case FileStatus.Deleted:
-                    return oldStatus;                    
             }
             StatusKeeper.SetFileStatus(path, status);
             return status;
diff --git a/trunk/Pithos.Interfaces/FileInfoExtensions.cs b/trunk/Pithos.Interfaces/FileInfoExtensions.cs
new file mode 100644 (file)
index 0000000..06a6721
--- /dev/null
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+
+namespace Pithos.Interfaces
+{
+    public static class FileInfoExtensions
+    {
+        public static  string AsRelativeTo(this FileInfo fileInfo,string path )
+        {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");            
+            Contract.EndContractBlock();
+            
+
+            if (!path.EndsWith("\\"))
+                path=path.ToLower() + "\\";
+            int pathLength = path.Length;            
+            
+            var filePath = fileInfo.FullName;
+
+            if (!filePath.StartsWith(path,StringComparison.InvariantCultureIgnoreCase))
+                throw new ArgumentException(String.Format("The path {0} doesn't contain the file {1}",path,filePath));
+            
+            var relativePath = filePath.Substring(pathLength, filePath.Length - pathLength);
+
+            return relativePath;
+        }
+
+        public static string AsRelativeUrlTo(this FileInfo fileInfo,string path )
+        {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            Contract.EndContractBlock();
+
+            var relativePath = fileInfo.AsRelativeTo(path);
+            var replacedSlashes = relativePath.Replace("\\","/");
+            var escaped = Uri.EscapeUriString(replacedSlashes);
+            return escaped;
+        }
+
+        public static string RelativeUriToFilePath(this Uri uri)
+        {
+            var unescaped = Uri.UnescapeDataString(uri.ToString());
+            var path = unescaped.Replace("/", "\\");
+            return path;
+        }
+
+
+
+    }
+}
index 0e6a3ff..eec711a 100644 (file)
@@ -79,6 +79,23 @@ namespace Pithos.Interfaces
 
         public string Container { get; set; }
 
+        public ObjectInfo()
+        {}
+
+        public ObjectInfo(string accountPath,string accountName,FileInfo fileInfo)
+        {
+            var relativeUrl = fileInfo.AsRelativeUrlTo(accountPath);
+            //The first part of the URL is the container
+            var slashIndex = relativeUrl.IndexOf('/');
+            var container = relativeUrl.Substring(0, slashIndex);
+            //The second is the file's url relative to the container
+            var fileUrl = relativeUrl.Substring(slashIndex + 1);
+
+            Account = accountName;
+            Container = container;
+            Name = fileUrl; 
+        }
+
 
         private void ExtractKnownExtensions()
         {
index 9c92c1e..aaf4af5 100644 (file)
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AccountSettings.cs" />
+    <Compile Include="FileInfoExtensions.cs" />
     <Compile Include="IPithosSettings.cs" />
     <Compile Include="IStatusChecker.cs" />
     <Compile Include="PermissionConverter.cs" />
index 4f7c2d8..12b95bb 100644 (file)
@@ -76,7 +76,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="AsyncCtpLibrary">
-      <HintPath>C:\Users\Administrator\Documents\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary.dll</HintPath>
+      <HintPath>..\Libraries\AsyncCtpLibrary.dll</HintPath>
     </Reference>
     <Reference Include="Newtonsoft.Json, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
index 889c8dc..7dff317 100644 (file)
@@ -614,6 +614,18 @@ namespace Pithos.Network
                 {
                     case HttpStatusCode.OK:
                     case HttpStatusCode.NoContent:
+                        var keys = client.ResponseHeaders.AllKeys.AsQueryable();
+                        var tags = (from key in keys
+                                    where key.StartsWith("X-Container-Meta-")
+                                    let name = key.Substring(14)
+                                    select new { Name = name, Value = client.ResponseHeaders[name] })
+                                    .ToDictionary(t => t.Name, t => t.Value);
+                        var policies= (from key in keys
+                                    where key.StartsWith("X-Container-Policy-")
+                                    let name = key.Substring(14)
+                                    select new { Name = name, Value = client.ResponseHeaders[name] })
+                                    .ToDictionary(t => t.Name, t => t.Value);
+
                         var containerInfo = new ContainerInfo
                                                 {
                                                     Account=account,
@@ -623,8 +635,12 @@ namespace Pithos.Network
                                                     Bytes = long.Parse(client.GetHeaderValue("X-Container-Bytes-Used")),
                                                     BlockHash = client.GetHeaderValue("X-Container-Block-Hash"),
                                                     BlockSize=int.Parse(client.GetHeaderValue("X-Container-Block-Size")),
-                                                    Last_Modified=client.LastModified
+                                                    Last_Modified=client.LastModified,
+                                                    Tags=tags,
+                                                    Policies=policies
                                                 };
+                        
+
                         return containerInfo;
                     case HttpStatusCode.NotFound:
                         return ContainerInfo.Empty;
index e654f32..b132aa5 100644 (file)
@@ -1,4 +1,5 @@
 using System;
+using System.Collections.Generic;
 
 namespace Pithos.Network
 {
@@ -13,6 +14,14 @@ namespace Pithos.Network
 
         public DateTime Last_Modified { get; set; }
 
+        public Dictionary<string, string> Tags { get; set; }
+        public Dictionary<string, string> Policies { get; set; }
+
         public static ContainerInfo Empty=new ContainerInfo();
+
+        public ContainerInfo()
+        {
+            Tags = new Dictionary<string, string>();
+        }
     }
 }
\ No newline at end of file
index d6d3b53..2b95243 100644 (file)
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="AsyncCtpLibrary">
-      <HintPath>C:\Users\Administrator\Documents\Microsoft Visual Studio Async CTP\Samples\AsyncCtpLibrary.dll</HintPath>
+      <HintPath>..\Libraries\AsyncCtpLibrary.dll</HintPath>
     </Reference>
     <Reference Include="log4net">
       <HintPath>..\Libraries\log4net.dll</HintPath>
index a76722d..931fd19 100644 (file)
@@ -13,6 +13,7 @@ using System.Runtime.Serialization;
 using System.Threading.Tasks;
 using log4net;
 
+
 namespace Pithos.Network
 {
     using System;
@@ -108,7 +109,7 @@ namespace Pithos.Network
 
         protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
         {
-            return ProcessResponse(()=>base.GetWebResponse(request, result));
+            return ProcessResponse(()=>base.GetWebResponse(request, result)); 
         }
 
         protected override WebResponse GetWebResponse(WebRequest request)
@@ -177,6 +178,7 @@ namespace Pithos.Network
 
         public string DownloadStringWithRetry(string address,int retries=0)
         {
+            
             if (address == null)
                 throw new ArgumentNullException("address");
 
@@ -185,7 +187,6 @@ namespace Pithos.Network
             TraceStart("GET",actualAddress);            
             
             var actualRetries = (retries == 0) ? Retries : retries;
-            
 
             
             var task = Retry(() =>