Modifications to delete folder contents
authorPanagiotis Kanavos <pkanavos@gmail.com>
Wed, 11 Jan 2012 21:22:39 +0000 (23:22 +0200)
committerPanagiotis Kanavos <pkanavos@gmail.com>
Wed, 11 Jan 2012 21:22:39 +0000 (23:22 +0200)
trunk/Pithos.Core.Test/MockStatusKeeper.cs
trunk/Pithos.Core/Agents/CloudTransferAction.cs
trunk/Pithos.Core/Agents/FileAgent.cs
trunk/Pithos.Core/Agents/NetworkAgent.cs
trunk/Pithos.Core/Agents/StatusAgent.cs
trunk/Pithos.Core/Agents/WorkflowAgent.cs
trunk/Pithos.Core/FileState.cs
trunk/Pithos.Core/IStatusKeeper.cs
trunk/Pithos.Interfaces/ObjectInfo.cs
trunk/Pithos.Network/RestClient.cs

index f2869e8..2834922 100644 (file)
@@ -136,6 +136,16 @@ namespace Pithos.Core.Test
             throw new NotImplementedException();
         }
 
+        public void ClearFolderStatus(string path)
+        {
+            throw new NotImplementedException();
+        }
+
+        public IEnumerable<FileState> GetChildren(FileState fileState)
+        {
+            throw new NotImplementedException();
+        }
+
 
         private PithosStatus _pithosStatus = PithosStatus.InSynch;
         public void SetPithosStatus(PithosStatus status)
index 8366037..7b08c19 100644 (file)
@@ -110,7 +110,7 @@ namespace Pithos.Core.Agents
     public class CloudDeleteAction:CloudAction
     {
         public CloudDeleteAction(AccountInfo accountInfo,FileSystemInfo fileInfo, FileState fileState)
-            : this(accountInfo,fileInfo,new ObjectInfo(accountInfo.AccountPath,accountInfo.UserName,fileInfo),fileState)
+            : this(accountInfo,fileInfo,new ObjectInfo(accountInfo.AccountPath,accountInfo.UserName,fileInfo.WithProperCapitalization()),fileState)
         {            
         }
 
index c6a6fbd..8218cc6 100644 (file)
@@ -210,8 +210,7 @@ namespace Pithos.Core.Agents
             var filePath = e.FullPath;
             if (Ignore(filePath)) 
                 return;
-          /*  if (Directory.Exists(filePath))
-                return;    */        
+
             _agent.Post(new WorkflowState{AccountInfo=AccountInfo, Path = filePath, FileName = e.Name, TriggeringChange = e.ChangeType });
         }
 
index 584532c..9a9d9e2 100644 (file)
@@ -45,6 +45,7 @@ using System.IO;
 using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
+using System.Threading.Tasks.Dataflow;
 using Castle.ActiveRecord;
 using Pithos.Interfaces;
 using Pithos.Network;
@@ -59,7 +60,7 @@ namespace Pithos.Core.Agents
         private Agent<CloudAction> _agent;
 
         //A separate agent is used to execute delete actions immediatelly;
-        private Agent<CloudDeleteAction> _deleteAgent;
+        private ActionBlock<CloudDeleteAction> _deleteAgent;
         readonly ConcurrentDictionary<string,DateTime> _deletedFiles=new ConcurrentDictionary<string, DateTime>();
 
         [System.ComponentModel.Composition.Import]
@@ -86,8 +87,8 @@ namespace Pithos.Core.Agents
                 loop();
             });
 
-            _deleteAgent = Agent<CloudDeleteAction>.Start(inbox =>
-            {
+            _deleteAgent = new ActionBlock<CloudDeleteAction>(message =>ProcessDelete(message),new ExecutionDataflowBlockOptions{MaxDegreeOfParallelism=4});
+            /*
                 Action loop = null;
                 loop = () =>
                             {
@@ -96,8 +97,8 @@ namespace Pithos.Core.Agents
                                 inbox.LoopAsync(process, loop);
                             };
                 loop();
+*/
 
-            });
         }
 
         private async Task Process(CloudAction action)
@@ -128,7 +129,8 @@ namespace Pithos.Core.Agents
                     if (IsDeletedFile(action))
                     {
                         //Clear the status of already deleted files to avoid reprocessing
-                        this.StatusKeeper.ClearFileStatus(action.LocalFile.FullName);
+                        if (action.LocalFile != null)
+                            this.StatusKeeper.ClearFileStatus(action.LocalFile.FullName);
                     }
                     else
                     {
@@ -231,8 +233,10 @@ namespace Pithos.Core.Agents
                         var key = GetFileKey(action.CloudFile);
                         _deletedFiles[key]=DateTime.Now;
 
+
                         // and then delete the file from the server
                         DeleteCloudFile(accountInfo, cloudFile);
+
                         Log.InfoFormat("[ACTION] End Delete {0}:{1}->{2}", action.Action, action.LocalFile,
                                        action.CloudFile.Name);
                     }
@@ -949,7 +953,7 @@ namespace Pithos.Core.Agents
                         //If the directory doesn't exist the Hash property will be empty
                         if (String.IsNullOrWhiteSpace(info.Hash))
                             //Go on and create the directory
-                            client.PutObject(account, cloudFile.Container, cloudFile.Name, fullFileName, String.Empty, "application/directory");
+                            await client.PutObject(account, cloudFile.Container, cloudFile.Name, fullFileName, String.Empty, "application/directory");
                     }
                     else
                     {
index 67dafb2..f630587 100644 (file)
@@ -149,7 +149,7 @@ namespace Pithos.Core.Agents
                 if (fileState == null)
                 {
                     //This is a new file
-                    var fullPath = pair.File.FullName.ToLower();
+                    var fullPath = pair.File.FullName;
                     var createState = FileState.CreateForAsync(fullPath, BlockSize, BlockHash);
                     createState.ContinueWith(state => _persistenceAgent.Post(state.Result.Create));
                 }                
@@ -217,14 +217,14 @@ namespace Pithos.Core.Agents
                     using (var connection = GetConnection())
                     using (
                         var command =
-                            new SQLiteCommand("update FileState set FileStatus= :fileStatus where FilePath = :path ",
+                            new SQLiteCommand("update FileState set FileStatus= :fileStatus where FilePath = :path COLLATE NOCASE",
                                               connection))
                     {
 
 
                         command.Parameters.AddWithValue("fileStatus", status);
 
-                        command.Parameters.AddWithValue("path", path.ToLower());
+                        command.Parameters.AddWithValue("path", path);
                         
                         var affected = command.ExecuteNonQuery();
                         return affected;
@@ -251,11 +251,11 @@ namespace Pithos.Core.Agents
                     using (
                         var command =
                             new SQLiteCommand(
-                                "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path  ",
+                                "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path COLLATE NOCASE ",
                                 connection))
                     {
 
-                        command.Parameters.AddWithValue("path", absolutePath.ToLower());
+                        command.Parameters.AddWithValue("path", absolutePath);
                         command.Parameters.AddWithValue("fileStatus", fileStatus);
                         command.Parameters.AddWithValue("overlayStatus", overlayStatus);
                         
@@ -320,10 +320,10 @@ namespace Pithos.Core.Agents
             {
                 
                 using (var connection = GetConnection())
-                using (var command = new SQLiteCommand("select Id, FilePath, OverlayStatus,FileStatus ,Checksum   ,Version    ,VersionTimeStamp,IsShared   ,SharedBy   ,ShareWrite  from FileState where FilePath=:path", connection))
+                using (var command = new SQLiteCommand("select Id, FilePath, OverlayStatus,FileStatus ,Checksum   ,Version    ,VersionTimeStamp,IsShared   ,SharedBy   ,ShareWrite  from FileState where FilePath=:path COLLATE NOCASE", connection))
                 {
                     
-                    command.Parameters.AddWithValue("path", path.ToLower());
+                    command.Parameters.AddWithValue("path", path);
                     
                     using (var reader = command.ExecuteReader())
                     {
@@ -388,10 +388,10 @@ namespace Pithos.Core.Agents
             {
                 
                 using (var connection = GetConnection())
-                using (var command = new SQLiteCommand("select OverlayStatus from FileState where FilePath=:path", connection))
+                using (var command = new SQLiteCommand("select OverlayStatus from FileState where FilePath=:path  COLLATE NOCASE", connection))
                 {
                     
-                    command.Parameters.AddWithValue("path", path.ToLower());
+                    command.Parameters.AddWithValue("path", path);
                     
                     var s = command.ExecuteScalar();
                     return (FileOverlayStatus) Convert.ToInt32(s);
@@ -431,7 +431,7 @@ namespace Pithos.Core.Agents
                 throw new ArgumentException("The path must be rooted","path");
             Contract.EndContractBlock();
 
-            _persistenceAgent.Post(() => FileState.StoreOverlayStatus(path.ToLower(),overlayStatus));
+            _persistenceAgent.Post(() => FileState.StoreOverlayStatus(path,overlayStatus));
         }
 
        /* public void RenameFileOverlayStatus(string oldPath, string newPath)
@@ -460,7 +460,7 @@ namespace Pithos.Core.Agents
             Debug.Assert(!path.Contains(FolderConstants.CacheFolder));
             Debug.Assert(!path.EndsWith(".ignore"));
 
-            _persistenceAgent.Post(() => UpdateStatusDirect(path.ToLower(), fileStatus, overlayStatus));
+            _persistenceAgent.Post(() => UpdateStatusDirect(path, fileStatus, overlayStatus));
         }
 
 /*
@@ -528,7 +528,7 @@ namespace Pithos.Core.Agents
                 {
                     if (StateExists(path, connection))
                         command.CommandText =
-                            "update FileState set FileStatus= :fileStatus where FilePath = :path  ";
+                            "update FileState set FileStatus= :fileStatus where FilePath = :path  COLLATE NOCASE ";
                     else
                     {
                         command.CommandText =
@@ -536,7 +536,7 @@ namespace Pithos.Core.Agents
                         command.Parameters.AddWithValue("id", Guid.NewGuid());
                     }
 
-                    command.Parameters.AddWithValue("path", path.ToLower());
+                    command.Parameters.AddWithValue("path", path);
                     command.Parameters.AddWithValue("checksum", objectInfo.Hash);
                     command.Parameters.AddWithValue("version", objectInfo.Version);
                     command.Parameters.AddWithValue("versionTimeStamp",
@@ -558,9 +558,9 @@ namespace Pithos.Core.Agents
 
         private bool StateExists(string filePath,SQLiteConnection connection)
         {
-            using (var command = new SQLiteCommand("Select count(*) from FileState where FilePath=:path", connection))
+            using (var command = new SQLiteCommand("Select count(*) from FileState where FilePath=:path  COLLATE NOCASE", connection))
             {
-                command.Parameters.AddWithValue("path", filePath.ToLower());
+                command.Parameters.AddWithValue("path", filePath);
                 var result = command.ExecuteScalar();
                 return ((long)result >= 1);
             }
@@ -575,7 +575,7 @@ namespace Pithos.Core.Agents
                 throw new ArgumentException("The path must be rooted", "path");
             Contract.EndContractBlock();
             
-            _persistenceAgent.Post(() => UpdateStatusDirect(path.ToLower(), status));
+            _persistenceAgent.Post(() => UpdateStatusDirect(path, status));
         }
 
         public FileStatus GetFileStatus(string path)
@@ -589,14 +589,18 @@ namespace Pithos.Core.Agents
             
             using (var connection = GetConnection())
             {
-                var command = new SQLiteCommand("select FileStatus from FileState where FilePath=:path", connection);
-                command.Parameters.AddWithValue("path", path.ToLower());
+                var command = new SQLiteCommand("select FileStatus from FileState where FilePath=:path  COLLATE NOCASE", connection);
+                command.Parameters.AddWithValue("path", path);
                 
                 var s = command.ExecuteScalar();
                 return (FileStatus)Convert.ToInt32(s);
             }
         }
 
+        /// <summary>
+        /// Deletes the status of the specified file
+        /// </summary>
+        /// <param name="path"></param>
         public void ClearFileStatus(string path)
         {
             if (String.IsNullOrWhiteSpace(path))
@@ -608,6 +612,33 @@ namespace Pithos.Core.Agents
             _persistenceAgent.Post(() => DeleteDirect(path));   
         }
 
+        /// <summary>
+        /// Deletes the status of the specified folder and all its contents
+        /// </summary>
+        /// <param name="path"></param>
+        public void ClearFolderStatus(string path)
+        {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");
+            Contract.EndContractBlock();
+
+            _persistenceAgent.Post(() => DeleteFolderDirect(path));   
+        }
+
+        public IEnumerable<FileState> GetChildren(FileState fileState)
+        {
+            if (fileState == null)
+                throw new ArgumentNullException("fileState");
+            Contract.EndContractBlock();
+
+            var children = from state in FileState.Queryable
+                           where state.FilePath.StartsWith(fileState.FilePath + "\\")
+                           select state;
+            return children;
+        }
+
         private int DeleteDirect(string filePath)
         {
             using (log4net.ThreadContext.Stacks["StatusAgent"].Push("DeleteDirect"))
@@ -619,10 +650,38 @@ namespace Pithos.Core.Agents
                     
                     using (var connection = GetConnection())
                     {
-                        var command = new SQLiteCommand("delete from FileState where FilePath = :path",
+                        var command = new SQLiteCommand("delete from FileState where FilePath = :path  COLLATE NOCASE",
+                                                        connection);
+
+                        command.Parameters.AddWithValue("path", filePath);
+                        
+                        var affected = command.ExecuteNonQuery();
+                        return affected;
+                    }
+                }
+                catch (Exception exc)
+                {
+                    Log.Error(exc.ToString());
+                    throw;
+                }
+            }
+        }
+
+        private int DeleteFolderDirect(string filePath)
+        {
+            using (log4net.ThreadContext.Stacks["StatusAgent"].Push("DeleteDirect"))
+            {
+
+                try
+                {
+
+                    
+                    using (var connection = GetConnection())
+                    {
+                        var command = new SQLiteCommand("delete from FileState where FilePath = :path or FilePath like :path + '/%'  COLLATE NOCASE",
                                                         connection);
 
-                        command.Parameters.AddWithValue("path", filePath.ToLower());
+                        command.Parameters.AddWithValue("path", filePath);
                         
                         var affected = command.ExecuteNonQuery();
                         return affected;
@@ -644,7 +703,7 @@ namespace Pithos.Core.Agents
                 throw new ArgumentException("The path must be rooted", "path");            
             Contract.EndContractBlock();
 
-            _persistenceAgent.Post(() => FileState.UpdateChecksum(path.ToLower(), checksum));
+            _persistenceAgent.Post(() => FileState.UpdateChecksum(path, checksum));
         }
 
     }
index 4217bc4..02155e9 100644 (file)
@@ -97,18 +97,15 @@ namespace Pithos.Core.Agents
                         if (Log.IsDebugEnabled) Log.DebugFormat("Skipping {0}", state.FileName);
 
                         return CompletedTask<object>.Default;
-                    }
-                    string path = state.Path.ToLower();
-
-
+                    }                    
 
-                    FileSystemInfo info = Directory.Exists(path) ? (FileSystemInfo) new DirectoryInfo(path) : new FileInfo(path);
+                    var info = Directory.Exists(state.Path) ? (FileSystemInfo)new DirectoryInfo(state.Path) : new FileInfo(state.Path);
 
                     //Bypass deleted files, unless the status is Deleted
                     if (!info.Exists && state.Status != FileStatus.Deleted)
                     {
                         state.Skip = true;
-                        this.StatusKeeper.ClearFileStatus(path);
+                        this.StatusKeeper.ClearFileStatus(state.Path);
 
                         if (Log.IsDebugEnabled) Log.DebugFormat("Skipped missing {0}", state.FileName);
 
@@ -118,7 +115,7 @@ namespace Pithos.Core.Agents
                     using (new SessionScope(FlushAction.Never))
                     {
 
-                        var fileState = StatusKeeper.GetStateByFilePath(path);
+                        var fileState = StatusKeeper.GetStateByFilePath(state.Path);
 
                         switch (state.Status)
                         {
@@ -129,6 +126,17 @@ namespace Pithos.Core.Agents
                                                                         accountInfo.BlockHash));
                                 break;
                             case FileStatus.Deleted:
+                                if (fileState != null)
+                                {
+                                    var children = StatusKeeper.GetChildren(fileState);
+                                    foreach (var child in children)
+                                    {
+                                        var childInfo = child.IsFolder
+                                                            ? (FileSystemInfo) new DirectoryInfo(child.FilePath)
+                                                            : new FileInfo(child.FilePath);
+                                        NetworkAgent.Post(new CloudDeleteAction(accountInfo, childInfo, child));
+                                    }
+                                }
                                 NetworkAgent.Post(new CloudDeleteAction(accountInfo, info, fileState));
                                 break;
                             case FileStatus.Renamed:
index 519fbf2..90182d3 100644 (file)
@@ -59,18 +59,14 @@ namespace Pithos.Core
     {
         private static readonly ILog Log = LogManager.GetLogger("FileState");
 
-        private string _filePath;
         private IList<FileTag> _tags = new List<FileTag>();
 
         [PrimaryKey(PrimaryKeyType.Guid)]
         public Guid Id { get; set; }
 
+        
         [Property(Unique = true, UniqueKey = "IX_FileState_FilePath")]
-        public string FilePath
-        {
-            get { return _filePath; }
-            set { _filePath = value.ToLower(); }
-        }
+        public string FilePath { get; set; }
 
         [Property]
         public FileOverlayStatus OverlayStatus { get; set; }
@@ -98,6 +94,8 @@ namespace Pithos.Core
         [Property]
         public bool ShareWrite { get; set; }
 
+        [Property]
+        public bool IsFolder{ get; set; }
 
         [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true, Inverse = true)]
         public IList<FileTag> Tags
@@ -117,7 +115,7 @@ namespace Pithos.Core
 
                 
 
-                return Queryable.FirstOrDefault(s => s.FilePath == absolutePath.ToLower());
+                return Queryable.FirstOrDefault(s => s.FilePath == absolutePath);
             }
             catch (Exception ex)
             {
@@ -138,7 +136,7 @@ namespace Pithos.Core
                         {
                             const string hqlDelete = "delete FileState where FilePath = :path";
                             var deletedEntities = session.CreateQuery(hqlDelete)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .ExecuteUpdate();
                             return deletedEntities;
                         }, null);
@@ -153,18 +151,19 @@ namespace Pithos.Core
 
             ExecuteWithRetry((session, instance) =>
                         {
-                            const string hqlUpdate = "update FileState set FileStatus= :status where FilePath = :path  ";
+                            const string hqlUpdate = "update FileState set FileStatus= :status where FilePath = :path ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .SetEnum("status", newStatus)
                                 .ExecuteUpdate();
                             if (updatedEntities == 0)
                             {
                                 var newState = new FileState
                                                    {
-                                                       FilePath = absolutePath.ToLower(),
+                                                       FilePath = absolutePath,
                                                        Id = Guid.NewGuid(),
-                                                       FileStatus = newStatus
+                                                       FileStatus = newStatus,
+                                                       IsFolder=Directory.Exists(absolutePath)
                                                    };
                                 newState.CreateAndFlush();
                             }
@@ -182,10 +181,10 @@ namespace Pithos.Core
             ExecuteWithRetry((session, instance) =>
                         {
                             const string hqlUpdate =
-                                "update FileState set OverlayStatus= :status where FilePath = :path  ";
-                            var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
-                                .SetEnum("status", newStatus)
+                                "update FileState set OverlayStatus= :status where FilePath = :path ";
+                            var updatedEntities = session.CreateQuery(hqlUpdate)                                
+                                .SetString("path", absolutePath)
+                                .SetEnum("status", newStatus)                                
                                 .ExecuteUpdate();
                             if (updatedEntities == 0)
                             {
@@ -193,7 +192,8 @@ namespace Pithos.Core
                                                    {
                                                        FilePath = absolutePath,
                                                        Id = Guid.NewGuid(),
-                                                       OverlayStatus = newStatus
+                                                       OverlayStatus = newStatus,
+                                                       IsFolder=Directory.Exists(absolutePath)
                                                    };
                                 newState.CreateAndFlush();
                             }
@@ -214,7 +214,7 @@ namespace Pithos.Core
                             const string hqlUpdate =
                                 "update FileState set OverlayStatus= :overlayStatus, FileStatus= :fileStatus where FilePath = :path  ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .SetEnum("fileStatus", fileStatus)
                                 .SetEnum("overlayStatus", overlayStatus)
                                 .ExecuteUpdate();
@@ -236,7 +236,7 @@ namespace Pithos.Core
                             const string hqlUpdate =
                                 "update FileState set FileStatus= :fileStatus where FilePath = :path  ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .SetEnum("fileStatus", fileStatus)
                                 .ExecuteUpdate();
                             return updatedEntities;
@@ -254,10 +254,10 @@ namespace Pithos.Core
             ExecuteWithRetry((session, instance) =>
                         {
                             const string hqlUpdate =
-                                "update FileState set FilePath= :newPath where FilePath = :oldPath  ";
+                                "update FileState set FilePath= :newPath where FilePath = :oldPath ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("oldPath", oldPath.ToLower())
-                                .SetString("newPath", newPath.ToLower())
+                                .SetString("oldPath", oldPath)
+                                .SetString("newPath", newPath)
                                 .ExecuteUpdate();
                             return updatedEntities;
                         }, null);
@@ -287,9 +287,9 @@ namespace Pithos.Core
 
             ExecuteWithRetry((session, instance) =>
                         {
-                            const string hqlUpdate = "update FileState set Checksum= :checksum where FilePath = :path  ";
+                            const string hqlUpdate = "update FileState set Checksum= :checksum where FilePath = :path ";
                             var updatedEntities = session.CreateQuery(hqlUpdate)
-                                .SetString("path", absolutePath.ToLower())
+                                .SetString("path", absolutePath)
                                 .SetString("checksum", checksum)
                                 .ExecuteUpdate();
                             return updatedEntities;
@@ -320,8 +320,8 @@ namespace Pithos.Core
                                 const string hqlUpdate =
                                     "update FileState set FilePath = replace(FilePath,:oldPath,:newPath) where FilePath like :oldPath || '%' ";
                                 var renames = session.CreateQuery(hqlUpdate)
-                                    .SetString("oldPath", oldPath.ToLower())
-                                    .SetString("newPath", newPath.ToLower())
+                                    .SetString("oldPath", oldPath)
+                                    .SetString("newPath", newPath)
                                     .ExecuteUpdate();
                                 return renames;
                             }, null);
@@ -338,7 +338,7 @@ namespace Pithos.Core
 
             var fileState = new FileState
                                 {
-                                    FilePath = filePath.ToLower(),
+                                    FilePath = filePath,
                                     OverlayStatus = FileOverlayStatus.Unversioned,
                                     FileStatus = FileStatus.Created,
                                     Id = Guid.NewGuid()
index d45548c..9b9e4f1 100644 (file)
@@ -31,6 +31,8 @@ namespace Pithos.Core
         int BlockSize { get; set; }
         void ChangeRoots(string oldPath, string newPath);
         FileState GetStateByFilePath(string path);
+        void ClearFolderStatus(string path);
+        IEnumerable<FileState> GetChildren(FileState fileState);
     }
 
     [ContractClassFor(typeof(IStatusKeeper))]
@@ -172,5 +174,18 @@ namespace Pithos.Core
 
             return null;
         }
+
+        public void ClearFolderStatus(string path)
+        {
+            Contract.Requires(!String.IsNullOrWhiteSpace(path));
+            Contract.Requires(Path.IsPathRooted(path));
+        }
+
+        public IEnumerable<FileState> GetChildren(FileState fileState)
+        {
+            Contract.Requires(fileState!=null);
+            Contract.Ensures(Contract.Result<IEnumerable<FileState>>()!=null);
+            return default(IEnumerable<FileState>);
+        }
     }
 }
index af80368..fb48a95 100644 (file)
@@ -124,7 +124,7 @@ namespace Pithos.Interfaces
                 throw new ArgumentNullException("fileInfo");
             Contract.EndContractBlock();
 
-            var relativeUrl = fileInfo.AsRelativeUrlTo(accountPath);
+            var relativeUrl = fileInfo.WithProperCapitalization().AsRelativeUrlTo(accountPath);
             //The first part of the URL is the container
             var slashIndex = relativeUrl.IndexOf('/');
             var container = relativeUrl.Substring(0, slashIndex);
index 42aee54..a63d0c7 100644 (file)
@@ -226,7 +226,7 @@ namespace Pithos.Network
             //The response stream must be copied to avoid affecting other code by disposing of the 
             //original response stream.
             var stream = webResponse.GetResponseStream();            
-            using(var memStream=new MemoryStream((int) stream.Length))
+            using(var memStream=new MemoryStream())
             using (var reader = new StreamReader(memStream))
             {
                 stream.CopyTo(memStream);