Merge branch 'master' of https://code.grnet.gr/git/pithos-ms-client
authorGeorge Pantazis <gpant@noc.grnet.gr>
Mon, 30 Apr 2012 17:23:28 +0000 (20:23 +0300)
committerGeorge Pantazis <gpant@noc.grnet.gr>
Mon, 30 Apr 2012 17:23:28 +0000 (20:23 +0300)
Conflicts:
trunk/Pithos.Client.WPF/Properties/AssemblyInfo.cs

Signed-off-by: George Pantazis <gpant@noc.grnet.gr>

trunk/Pithos.Client.WPF/Properties/AssemblyInfo.cs
trunk/Pithos.Core/Agents/Downloader.cs
trunk/Pithos.Core/Agents/SelectiveUris.cs
trunk/Pithos.Core/Agents/Uploader.cs
trunk/Pithos.Network.Test/CloudFilesClientTest.cs
trunk/Pithos.Network/TreeHash.cs

index 826915d..a040480 100644 (file)
@@ -92,6 +92,9 @@ using System.Windows;
 //
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
+<<<<<<< HEAD
 // [assembly: AssemblyVersion("1.0.*")]
+=======
+>>>>>>> 2b0ec5b83deb6c61ffae7943da4606733b0f5e76
 [assembly: AssemblyVersion("0.7.20430.0")]
 [assembly: AssemblyFileVersionAttribute("0.7.20430.0")]
index ef2c5a9..9ba896e 100644 (file)
@@ -168,13 +168,13 @@ namespace Pithos.Core.Agents
             //Calculate the file's treehash
 
             //TODO: Should pass cancellation token here
-            var treeHash = await Signature.CalculateTreeHashAsync(localPath, serverHash.BlockSize, serverHash.BlockHash, 2);
+            var treeHash = await Signature.CalculateTreeHashAsync(localPath, (int)serverHash.BlockSize, serverHash.BlockHash, 2);
 
             //And compare it with the server's hash
             var upHashes = serverHash.GetHashesAsStrings();
             var localHashes = treeHash.HashDictionary;
             ReportDownloadProgress(Path.GetFileName(localPath), 0, upHashes.Length, cloudFile.Bytes);
-            for (int i = 0; i < upHashes.Length; i++)
+            for (var i = 0; i < upHashes.Length; i++)
             {\r
                 if (await WaitOrAbort(cloudFile, cancellationToken))\r
                     return;
index 884d7d8..ee2fa49 100644 (file)
@@ -1,80 +1,80 @@
 using System;\r
 using System.Collections.Concurrent;\r
-using System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.IO;
-using System.Linq;
-using System.Text;
-using Pithos.Interfaces;
-using Pithos.Network;
-
-namespace Pithos.Core.Agents
-{
-    [Export(typeof(Selectives))]
-    public class Selectives
-    {
-
-        public ConcurrentDictionary<Uri, List<Uri>> SelectiveUris { get; private set; }
-
-        private ConcurrentDictionary<Uri, List<string>> SelectivePaths { get; set; }
-
-        public Selectives()
+using System.Collections.Generic;\r
+using System.ComponentModel.Composition;\r
+using System.IO;\r
+using System.Linq;\r
+using System.Text;\r
+using Pithos.Interfaces;\r
+using Pithos.Network;\r
+\r
+namespace Pithos.Core.Agents\r
+{\r
+    [Export(typeof(Selectives))]\r
+    public class Selectives\r
+    {\r
+\r
+        public ConcurrentDictionary<Uri, List<Uri>> SelectiveUris { get; private set; }\r
+\r
+        private ConcurrentDictionary<Uri, List<string>> SelectivePaths { get; set; }\r
+\r
+        public Selectives()\r
         {\r
             SelectiveUris = new ConcurrentDictionary<Uri, List<Uri>>();\r
-            SelectivePaths = new ConcurrentDictionary<Uri, List<string>>();
-        }
-
-        public void SetSelectedUris(AccountInfo account,List<Uri> uris)
-        {
-            SelectiveUris[account.AccountKey] = uris;
-            SelectivePaths[account.AccountKey] = UrisToFilePaths(account,uris);
-        }
-
-        public bool IsSelected(ObjectInfo info)
-        {
-            List<Uri> filterUris;
-            return !SelectiveUris.TryGetValue(info.AccountKey, out filterUris) 
-                || filterUris.Count ==0
-                || filterUris.Any(f => info.Uri.IsAtOrDirectlyBelow(f));
-        }
-
-        public bool IsSelected(AccountInfo account,FileSystemInfo info)
-        {
-            return IsSelected(account,info.FullName);
-        }
-
-        public bool IsSelected(AccountInfo account, string fullPath)
-        {
-            List<string> paths;
-            return !SelectivePaths.TryGetValue(account.AccountKey, out paths)
-                || paths.Count == 0
-                || paths.Any(fullPath.IsAtOrDirectlyBelow);
-        }
-
-        /// <summary>
-        /// Return a list of absolute filepaths from a list of Uris
-        /// </summary>
-        /// <param name="uris"></param>
-        /// <returns></returns>
-        private List<string> UrisToFilePaths(AccountInfo account,IEnumerable<Uri> uris)
-        {
-            if (uris == null)
-                return new List<string>();
-
-            var accountPath = account.AccountPath;
-            var storageUrl = account.StorageUri.ToString();
-            var own = (from uri in uris
-                       where uri.ToString().StartsWith(storageUrl)
-                       let relativePath = account.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()
-                       //Trim the account name
-                       select Path.Combine(accountPath, relativePath.After(account.UserName + '\\'))).ToList();
-            var others = (from uri in uris
-                          where !uri.ToString().StartsWith(storageUrl)
-                          let relativePath = account.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()
-                          //Trim the account name
-                          select Path.Combine(accountPath, "others-shared", relativePath)).ToList();
-            return own.Union(others).ToList();
-        }
-
-    }
-}
+            SelectivePaths = new ConcurrentDictionary<Uri, List<string>>();\r
+        }\r
+\r
+        public void SetSelectedUris(AccountInfo account,List<Uri> uris)\r
+        {\r
+            SelectiveUris[account.AccountKey] = uris;\r
+            SelectivePaths[account.AccountKey] = UrisToFilePaths(account,uris);\r
+        }\r
+\r
+        public bool IsSelected(ObjectInfo info)\r
+        {\r
+            List<Uri> filterUris;\r
+            return !SelectiveUris.TryGetValue(info.AccountKey, out filterUris) \r
+                || filterUris.Count ==0\r
+                || filterUris.Any(f => info.Uri.IsAtOrDirectlyBelow(f));\r
+        }\r
+\r
+        public bool IsSelected(AccountInfo account,FileSystemInfo info)\r
+        {\r
+            return IsSelected(account,info.FullName);\r
+        }\r
+\r
+        public bool IsSelected(AccountInfo account, string fullPath)\r
+        {\r
+            List<string> paths;\r
+            return !SelectivePaths.TryGetValue(account.AccountKey, out paths)\r
+                || paths.Count == 0\r
+                || paths.Any(fullPath.IsAtOrDirectlyBelow);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Return a list of absolute filepaths from a list of Uris\r
+        /// </summary>\r
+        /// <param name="uris"></param>\r
+        /// <returns></returns>\r
+        private List<string> UrisToFilePaths(AccountInfo account,IEnumerable<Uri> uris)\r
+        {\r
+            if (uris == null)\r
+                return new List<string>();\r
+\r
+            var accountPath = account.AccountPath;\r
+            var storageUrl = account.StorageUri.ToString();\r
+            var own = (from uri in uris\r
+                       where uri.ToString().StartsWith(storageUrl)\r
+                       let relativePath = account.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()\r
+                       //Trim the account name\r
+                       select Path.Combine(accountPath, relativePath.After(account.UserName + '\\'))).ToList();\r
+            var others = (from uri in uris\r
+                          where !uri.ToString().StartsWith(storageUrl)\r
+                          let relativePath = account.StorageUri.MakeRelativeUri(uri).RelativeUriToFilePath()\r
+                          //Trim the account name\r
+                          select Path.Combine(accountPath, "others-shared", relativePath)).ToList();\r
+            return own.Union(others).ToList();\r
+        }\r
+\r
+    }\r
+}\r
index 07e1072..168ada6 100644 (file)
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Reflection;
-using System.Threading;
-using System.Threading.Tasks;
-using Pithos.Interfaces;
-using Pithos.Network;
-using log4net;
-
-namespace Pithos.Core.Agents
-{
-    [Export(typeof(Uploader))]
-    public class Uploader
-    {
-        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
-        [Import]
-        private IStatusKeeper StatusKeeper { get; set; }
-
-        
-        public IStatusNotification StatusNotification { get; set; }
-
-        
-        //CancellationTokenSource _cts = new CancellationTokenSource();
-        /*public void SignalStop()
-        {
-            _cts.Cancel();
-        }*/
-
-        public async Task UploadCloudFile(CloudAction action,CancellationToken cancellationToken)
-        {
-            if (action == null)
-                throw new ArgumentNullException("action");
-            Contract.EndContractBlock();
-
-            using (ThreadContext.Stacks["Operation"].Push("UploadCloudFile"))
-            {
-                try
-                {
-                    await UnpauseEvent.WaitAsync();
-
-                    var fileInfo = action.LocalFile;
-
-                    if (fileInfo.Extension.Equals("ignore", StringComparison.InvariantCultureIgnoreCase))
-                        return;
-
-                    if (Selectives.IsSelected(action.AccountInfo, fileInfo))
-                        return;
-
-                    //Try to load the action's local state, if it is empty
-                    if (action.FileState == null)
-                        action.FileState = StatusKeeper.GetStateByFilePath(fileInfo.FullName);
-                    if (action.FileState == null)
-                    {
-                        Log.WarnFormat("File [{0}] has no local state. It was probably created by a download action", fileInfo.FullName);
-                        return;
-                    }
-
-                    var latestState = action.FileState;
-
-                    //Do not upload files in conflict
-                    if (latestState.FileStatus == FileStatus.Conflict)
-                    {
-                        Log.InfoFormat("Skipping file in conflict [{0}]", fileInfo.FullName);
-                        return;
-                    }
-                    //Do not upload files when we have no permission
-                    if (latestState.FileStatus == FileStatus.Forbidden)
-                    {
-                        Log.InfoFormat("Skipping forbidden file [{0}]", fileInfo.FullName);
-                        return;
-                    }
-
-                    //Are we targeting our own account or a sharer account?
-                    var relativePath = fileInfo.AsRelativeTo(action.AccountInfo.AccountPath);
-                    var accountInfo = relativePath.StartsWith(FolderConstants.OthersFolder) 
-                                                  ? GetSharerAccount(relativePath, action.AccountInfo) 
-                                                  : action.AccountInfo;
-
-
-
-                    var fullFileName = fileInfo.GetProperCapitalization();
-                    using (var gate = NetworkGate.Acquire(fullFileName, NetworkOperation.Uploading))
-                    {
-                        //Abort if the file is already being uploaded or downloaded
-                        if (gate.Failed)
-                            return;
-
-                        var cloudFile = action.CloudFile;
-                        var account = cloudFile.Account ?? accountInfo.UserName;
-                        try
-                        {
-
-                            var client = new CloudFilesClient(accountInfo);
-
-                            //Even if GetObjectInfo times out, we can proceed with the upload            
-                            var cloudInfo = client.GetObjectInfo(account, cloudFile.Container, cloudFile.Name);
-
-                            //If this a shared file
-                            if (!cloudFile.Account.Equals(action.AccountInfo.UserName,StringComparison.InvariantCultureIgnoreCase))
-                            {
-                                //If this is a read-only file, do not upload changes
-                                if (!cloudInfo.IsWritable(action.AccountInfo.UserName))
-                                {
-                                    MakeFileReadOnly(fullFileName);
-                                    return;
-                                }
-
-                                //If the file is new, can we upload it?
-                                if ( !cloudInfo.Exists && !client.CanUpload(account, cloudFile))
-                                {
-                                    MakeFileReadOnly(fullFileName);
-                                    return;
-                                }
-
-                            }
-
-                            await UnpauseEvent.WaitAsync();
-
-                            if (fileInfo is DirectoryInfo)
-                            {
-                                //If the directory doesn't exist the Hash property will be empty
-                                if (String.IsNullOrWhiteSpace(cloudInfo.Hash))
-                                    //Go on and create the directory
-                                    await client.PutObject(account, cloudFile.Container, cloudFile.Name, fullFileName,
-                                                         String.Empty, "application/directory");
-                            }
-                            else
-                            {
-
-                                var cloudHash = cloudInfo.Hash.ToLower();
-
-                                string topHash;
-                                TreeHash treeHash;
-                                using(StatusNotification.GetNotifier("Hashing {0} for Upload", "Finished hashing {0}",fileInfo.Name))
-                                {
-                                    treeHash = action.TreeHash.Value;
-                                    topHash = treeHash.TopHash.ToHashString();
-                                }
-
-                                //If the file hashes match, abort the upload
-                                if (cloudInfo != ObjectInfo.Empty && topHash == cloudHash)
-                                {
-                                    //but store any metadata changes 
-                                    StatusKeeper.StoreInfo(fullFileName, cloudInfo);
-                                    Log.InfoFormat("Skip upload of {0}, hashes match", fullFileName);
-                                    return;
-                                }
-
-
-                                //Mark the file as modified while we upload it
-                                StatusKeeper.SetFileOverlayStatus(fullFileName, FileOverlayStatus.Modified);
-                                //And then upload it
-
-                                //Upload even small files using the Hashmap. The server may already contain
-                                //the relevant block                                
-
-                                
-
-                                await UploadWithHashMap(accountInfo, cloudFile, fileInfo as FileInfo, cloudFile.Name, treeHash,cancellationToken);
-                            }
-                            //If everything succeeds, change the file and overlay status to normal
-                            StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal, "");
-                        }
-                        catch (WebException exc)
-                        {
-                            var response = (exc.Response as HttpWebResponse);
-                            if (response == null)
-                                throw;
-                            if (response.StatusCode == HttpStatusCode.Forbidden)
-                            {
-                                StatusKeeper.SetFileState(fileInfo.FullName, FileStatus.Forbidden, FileOverlayStatus.Conflict, "Forbidden");
-                                MakeFileReadOnly(fullFileName);
-                            }
-                            else
-                                //In any other case, propagate the error
-                                throw;
-                        }
-                    }
-                    //Notify the Shell to update the overlays
-                    NativeMethods.RaiseChangeNotification(fullFileName);
-                    StatusNotification.NotifyChangedFile(fullFileName);
-                }
-                catch (AggregateException ex)
-                {
-                    var exc = ex.InnerException as WebException;
-                    if (exc == null)
-                        throw ex.InnerException;
-                    if (HandleUploadWebException(action, exc))
-                        return;
-                    throw;
-                }
-                catch (WebException ex)
-                {
-                    if (HandleUploadWebException(action, ex))
-                        return;
-                    throw;
-                }
-                catch (Exception ex)
-                {
-                    Log.Error("Unexpected error while uploading file", ex);
-                    throw;
-                }
-            }
-        }
-
-        private static void MakeFileReadOnly(string fullFileName)
-        {
-            var attributes = File.GetAttributes(fullFileName);
-            //Do not make any modifications if not necessary
-            if (attributes.HasFlag(FileAttributes.ReadOnly))
-                return;
-            File.SetAttributes(fullFileName, attributes | FileAttributes.ReadOnly);
-        }
-
-        private static AccountInfo GetSharerAccount(string relativePath, AccountInfo accountInfo)
-        {
-            var parts = relativePath.Split('\\');
-            var accountName = parts[1];
-            var oldName = accountInfo.UserName;
-            var absoluteUri = accountInfo.StorageUri.AbsoluteUri;
-            var nameIndex = absoluteUri.IndexOf(oldName, StringComparison.Ordinal);
-            var root = absoluteUri.Substring(0, nameIndex);
-
-            accountInfo = new AccountInfo
-                              {
-                                  UserName = accountName,
-                                  AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),
-                                  StorageUri = new Uri(root + accountName),
-                                  BlockHash = accountInfo.BlockHash,
-                                  BlockSize = accountInfo.BlockSize,
-                                  Token = accountInfo.Token
-                              };
-            return accountInfo;
-        }
-
-
-        public async Task UploadWithHashMap(AccountInfo accountInfo, ObjectInfo cloudFile, FileInfo fileInfo, string url, TreeHash treeHash, CancellationToken token)
-        {
-            if (accountInfo == null)
-                throw new ArgumentNullException("accountInfo");
-            if (cloudFile == null)
-                throw new ArgumentNullException("cloudFile");
-            if (fileInfo == null)
-                throw new ArgumentNullException("fileInfo");
-            if (String.IsNullOrWhiteSpace(url))
-                throw new ArgumentNullException(url);
-            if (treeHash == null)
-                throw new ArgumentNullException("treeHash");
-            if (String.IsNullOrWhiteSpace(cloudFile.Container))
-                throw new ArgumentException("Invalid container", "cloudFile");
-            Contract.EndContractBlock();
-
-           
-            using (StatusNotification.GetNotifier("Uploading {0}", "Finished Uploading {0}", fileInfo.Name))
-            {
+using System;\r
+using System.Collections.Generic;\r
+using System.ComponentModel.Composition;\r
+using System.Diagnostics;\r
+using System.Diagnostics.Contracts;\r
+using System.IO;\r
+using System.Linq;\r
+using System.Net;\r
+using System.Reflection;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+using Pithos.Interfaces;\r
+using Pithos.Network;\r
+using log4net;\r
+\r
+namespace Pithos.Core.Agents\r
+{\r
+    [Export(typeof(Uploader))]\r
+    public class Uploader\r
+    {\r
+        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);\r
+\r
+        [Import]\r
+        private IStatusKeeper StatusKeeper { get; set; }\r
+\r
+        \r
+        public IStatusNotification StatusNotification { get; set; }\r
+\r
+        \r
+        //CancellationTokenSource _cts = new CancellationTokenSource();\r
+        /*public void SignalStop()\r
+        {\r
+            _cts.Cancel();\r
+        }*/\r
+\r
+        public async Task UploadCloudFile(CloudAction action,CancellationToken cancellationToken)\r
+        {\r
+            if (action == null)\r
+                throw new ArgumentNullException("action");\r
+            Contract.EndContractBlock();\r
+\r
+            using (ThreadContext.Stacks["Operation"].Push("UploadCloudFile"))\r
+            {\r
+                try\r
+                {\r
+                    await UnpauseEvent.WaitAsync();\r
+\r
+                    var fileInfo = action.LocalFile;\r
+\r
+                    if (fileInfo.Extension.Equals("ignore", StringComparison.InvariantCultureIgnoreCase))\r
+                        return;\r
+\r
+                    if (Selectives.IsSelected(action.AccountInfo, fileInfo))\r
+                        return;\r
+\r
+                    //Try to load the action's local state, if it is empty\r
+                    if (action.FileState == null)\r
+                        action.FileState = StatusKeeper.GetStateByFilePath(fileInfo.FullName);\r
+                    if (action.FileState == null)\r
+                    {\r
+                        Log.WarnFormat("File [{0}] has no local state. It was probably created by a download action", fileInfo.FullName);\r
+                        return;\r
+                    }\r
+\r
+                    var latestState = action.FileState;\r
+\r
+                    //Do not upload files in conflict\r
+                    if (latestState.FileStatus == FileStatus.Conflict)\r
+                    {\r
+                        Log.InfoFormat("Skipping file in conflict [{0}]", fileInfo.FullName);\r
+                        return;\r
+                    }\r
+                    //Do not upload files when we have no permission\r
+                    if (latestState.FileStatus == FileStatus.Forbidden)\r
+                    {\r
+                        Log.InfoFormat("Skipping forbidden file [{0}]", fileInfo.FullName);\r
+                        return;\r
+                    }\r
+\r
+                    //Are we targeting our own account or a sharer account?\r
+                    var relativePath = fileInfo.AsRelativeTo(action.AccountInfo.AccountPath);\r
+                    var accountInfo = relativePath.StartsWith(FolderConstants.OthersFolder) \r
+                                                  ? GetSharerAccount(relativePath, action.AccountInfo) \r
+                                                  : action.AccountInfo;\r
+\r
+\r
+\r
+                    var fullFileName = fileInfo.GetProperCapitalization();\r
+                    using (var gate = NetworkGate.Acquire(fullFileName, NetworkOperation.Uploading))\r
+                    {\r
+                        //Abort if the file is already being uploaded or downloaded\r
+                        if (gate.Failed)\r
+                            return;\r
+\r
+                        var cloudFile = action.CloudFile;\r
+                        var account = cloudFile.Account ?? accountInfo.UserName;\r
+                        try\r
+                        {\r
+\r
+                            var client = new CloudFilesClient(accountInfo);\r
+\r
+                            //Even if GetObjectInfo times out, we can proceed with the upload            \r
+                            var cloudInfo = client.GetObjectInfo(account, cloudFile.Container, cloudFile.Name);\r
+\r
+                            //If this a shared file\r
+                            if (!cloudFile.Account.Equals(action.AccountInfo.UserName,StringComparison.InvariantCultureIgnoreCase))\r
+                            {\r
+                                //If this is a read-only file, do not upload changes\r
+                                if (!cloudInfo.IsWritable(action.AccountInfo.UserName))\r
+                                {\r
+                                    MakeFileReadOnly(fullFileName);\r
+                                    return;\r
+                                }\r
+\r
+                                //If the file is new, can we upload it?\r
+                                if ( !cloudInfo.Exists && !client.CanUpload(account, cloudFile))\r
+                                {\r
+                                    MakeFileReadOnly(fullFileName);\r
+                                    return;\r
+                                }\r
+\r
+                            }\r
+\r
+                            await UnpauseEvent.WaitAsync();\r
+\r
+                            if (fileInfo is DirectoryInfo)\r
+                            {\r
+                                //If the directory doesn't exist the Hash property will be empty\r
+                                if (String.IsNullOrWhiteSpace(cloudInfo.Hash))\r
+                                    //Go on and create the directory\r
+                                    await client.PutObject(account, cloudFile.Container, cloudFile.Name, fullFileName,\r
+                                                         String.Empty, "application/directory");\r
+                            }\r
+                            else\r
+                            {\r
+\r
+                                var cloudHash = cloudInfo.Hash.ToLower();\r
+\r
+                                string topHash;\r
+                                TreeHash treeHash;\r
+                                using(StatusNotification.GetNotifier("Hashing {0} for Upload", "Finished hashing {0}",fileInfo.Name))\r
+                                {\r
+                                    treeHash = action.TreeHash.Value;\r
+                                    topHash = treeHash.TopHash.ToHashString();\r
+                                }\r
+\r
+                                //If the file hashes match, abort the upload\r
+                                if (cloudInfo != ObjectInfo.Empty && topHash == cloudHash)\r
+                                {\r
+                                    //but store any metadata changes \r
+                                    StatusKeeper.StoreInfo(fullFileName, cloudInfo);\r
+                                    Log.InfoFormat("Skip upload of {0}, hashes match", fullFileName);\r
+                                    return;\r
+                                }\r
+\r
+\r
+                                //Mark the file as modified while we upload it\r
+                                StatusKeeper.SetFileOverlayStatus(fullFileName, FileOverlayStatus.Modified);\r
+                                //And then upload it\r
+\r
+                                //Upload even small files using the Hashmap. The server may already contain\r
+                                //the relevant block                                \r
+\r
+                                \r
+\r
+                                await UploadWithHashMap(accountInfo, cloudFile, fileInfo as FileInfo, cloudFile.Name, treeHash,cancellationToken);\r
+                            }\r
+                            //If everything succeeds, change the file and overlay status to normal\r
+                            StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal, "");\r
+                        }\r
+                        catch (WebException exc)\r
+                        {\r
+                            var response = (exc.Response as HttpWebResponse);\r
+                            if (response == null)\r
+                                throw;\r
+                            if (response.StatusCode == HttpStatusCode.Forbidden)\r
+                            {\r
+                                StatusKeeper.SetFileState(fileInfo.FullName, FileStatus.Forbidden, FileOverlayStatus.Conflict, "Forbidden");\r
+                                MakeFileReadOnly(fullFileName);\r
+                            }\r
+                            else\r
+                                //In any other case, propagate the error\r
+                                throw;\r
+                        }\r
+                    }\r
+                    //Notify the Shell to update the overlays\r
+                    NativeMethods.RaiseChangeNotification(fullFileName);\r
+                    StatusNotification.NotifyChangedFile(fullFileName);\r
+                }\r
+                catch (AggregateException ex)\r
+                {\r
+                    var exc = ex.InnerException as WebException;\r
+                    if (exc == null)\r
+                        throw ex.InnerException;\r
+                    if (HandleUploadWebException(action, exc))\r
+                        return;\r
+                    throw;\r
+                }\r
+                catch (WebException ex)\r
+                {\r
+                    if (HandleUploadWebException(action, ex))\r
+                        return;\r
+                    throw;\r
+                }\r
+                catch (Exception ex)\r
+                {\r
+                    Log.Error("Unexpected error while uploading file", ex);\r
+                    throw;\r
+                }\r
+            }\r
+        }\r
+\r
+        private static void MakeFileReadOnly(string fullFileName)\r
+        {\r
+            var attributes = File.GetAttributes(fullFileName);\r
+            //Do not make any modifications if not necessary\r
+            if (attributes.HasFlag(FileAttributes.ReadOnly))\r
+                return;\r
+            File.SetAttributes(fullFileName, attributes | FileAttributes.ReadOnly);\r
+        }\r
+\r
+        private static AccountInfo GetSharerAccount(string relativePath, AccountInfo accountInfo)\r
+        {\r
+            var parts = relativePath.Split('\\');\r
+            var accountName = parts[1];\r
+            var oldName = accountInfo.UserName;\r
+            var absoluteUri = accountInfo.StorageUri.AbsoluteUri;\r
+            var nameIndex = absoluteUri.IndexOf(oldName, StringComparison.Ordinal);\r
+            var root = absoluteUri.Substring(0, nameIndex);\r
+\r
+            accountInfo = new AccountInfo\r
+                              {\r
+                                  UserName = accountName,\r
+                                  AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),\r
+                                  StorageUri = new Uri(root + accountName),\r
+                                  BlockHash = accountInfo.BlockHash,\r
+                                  BlockSize = accountInfo.BlockSize,\r
+                                  Token = accountInfo.Token\r
+                              };\r
+            return accountInfo;\r
+        }\r
+\r
+\r
+        public async Task UploadWithHashMap(AccountInfo accountInfo, ObjectInfo cloudFile, FileInfo fileInfo, string url, TreeHash treeHash, CancellationToken token)\r
+        {\r
+            if (accountInfo == null)\r
+                throw new ArgumentNullException("accountInfo");\r
+            if (cloudFile == null)\r
+                throw new ArgumentNullException("cloudFile");\r
+            if (fileInfo == null)\r
+                throw new ArgumentNullException("fileInfo");\r
+            if (String.IsNullOrWhiteSpace(url))\r
+                throw new ArgumentNullException(url);\r
+            if (treeHash == null)\r
+                throw new ArgumentNullException("treeHash");\r
+            if (String.IsNullOrWhiteSpace(cloudFile.Container))\r
+                throw new ArgumentException("Invalid container", "cloudFile");\r
+            Contract.EndContractBlock();\r
+\r
+           \r
+            using (StatusNotification.GetNotifier("Uploading {0}", "Finished Uploading {0}", fileInfo.Name))\r
+            {\r
                 if (await WaitOrAbort(cloudFile, token)) \r
                     return;\r
 \r
-                var fullFileName = fileInfo.GetProperCapitalization();
-
-                var account = cloudFile.Account ?? accountInfo.UserName;
-                var container = cloudFile.Container;
-
-
-                var client = new CloudFilesClient(accountInfo);
-                //Send the hashmap to the server            
-                var missingHashes = await client.PutHashMap(account, container, url, treeHash);
-                int block = 0;
-                ReportUploadProgress(fileInfo.Name, block++, missingHashes.Count, fileInfo.Length);
-                //If the server returns no missing hashes, we are done
-                while (missingHashes.Count > 0)
+                var fullFileName = fileInfo.GetProperCapitalization();\r
+\r
+                var account = cloudFile.Account ?? accountInfo.UserName;\r
+                var container = cloudFile.Container;\r
+\r
+\r
+                var client = new CloudFilesClient(accountInfo);\r
+                //Send the hashmap to the server            \r
+                var missingHashes = await client.PutHashMap(account, container, url, treeHash);\r
+                int block = 0;\r
+                ReportUploadProgress(fileInfo.Name, block++, missingHashes.Count, fileInfo.Length);\r
+                //If the server returns no missing hashes, we are done\r
+                while (missingHashes.Count > 0)\r
                 {\r
 \r
                     if (await WaitOrAbort(cloudFile, token))\r
                         return;\r
-
-
-                    var buffer = new byte[accountInfo.BlockSize];
-                    foreach (var missingHash in missingHashes)
+\r
+\r
+                    var buffer = new byte[accountInfo.BlockSize];\r
+                    foreach (var missingHash in missingHashes)\r
                     {\r
                         if (await WaitOrAbort(cloudFile, token))\r
                             return;\r
-
-
-                        //Find the proper block
-                        var blockIndex = treeHash.HashDictionary[missingHash];
-                        long offset = blockIndex*accountInfo.BlockSize;
-
-                        var read = fileInfo.Read(buffer, offset, accountInfo.BlockSize);
-
-                        try
-                        {
-                            //And upload the block                
-                            await client.PostBlock(account, container, buffer, 0, read);
-                            Log.InfoFormat("[BLOCK] Block {0} of {1} uploaded", blockIndex, fullFileName);
-                        }
-                        catch (Exception exc)
-                        {
-                            Log.Error(String.Format("Uploading block {0} of {1}", blockIndex, fullFileName), exc);
-                        }
-                        ReportUploadProgress(fileInfo.Name, block++, missingHashes.Count, fileInfo.Length);
-                    }
-
-                    token.ThrowIfCancellationRequested();
-                    //Repeat until there are no more missing hashes                
-                    missingHashes = await client.PutHashMap(account, container, url, treeHash);
-                }
-
-                ReportUploadProgress(fileInfo.Name, missingHashes.Count, missingHashes.Count, fileInfo.Length);
-            }
+\r
+\r
+                        //Find the proper block\r
+                        var blockIndex = treeHash.HashDictionary[missingHash];\r
+                        long offset = blockIndex*accountInfo.BlockSize;\r
+\r
+                        var read = fileInfo.Read(buffer, offset, accountInfo.BlockSize);\r
+\r
+                        try\r
+                        {\r
+                            //And upload the block                \r
+                            await client.PostBlock(account, container, buffer, 0, read);\r
+                            Log.InfoFormat("[BLOCK] Block {0} of {1} uploaded", blockIndex, fullFileName);\r
+                        }\r
+                        catch (Exception exc)\r
+                        {\r
+                            Log.Error(String.Format("Uploading block {0} of {1}", blockIndex, fullFileName), exc);\r
+                        }\r
+                        ReportUploadProgress(fileInfo.Name, block++, missingHashes.Count, fileInfo.Length);\r
+                    }\r
+\r
+                    token.ThrowIfCancellationRequested();\r
+                    //Repeat until there are no more missing hashes                \r
+                    missingHashes = await client.PutHashMap(account, container, url, treeHash);\r
+                }\r
+\r
+                ReportUploadProgress(fileInfo.Name, missingHashes.Count, missingHashes.Count, fileInfo.Length);\r
+            }\r
         }\r
 \r
         private async Task<bool> WaitOrAbort(ObjectInfo cloudFile, CancellationToken token)\r
@@ -327,33 +327,33 @@ namespace Pithos.Core.Agents
             return shouldAbort;\r
         }\r
 \r
-        private void ReportUploadProgress(string fileName, int block, int totalBlocks, long fileSize)
-        {
-            StatusNotification.Notify(totalBlocks == 0
-                                          ? new ProgressNotification(fileName, "Uploading", 1, 1, fileSize)
-                                          : new ProgressNotification(fileName, "Uploading", block, totalBlocks, fileSize));
-        }
-
-
-        private bool HandleUploadWebException(CloudAction action, WebException exc)
-        {
-            var response = exc.Response as HttpWebResponse;
-            if (response == null)
-                throw exc;
-            if (response.StatusCode == HttpStatusCode.Unauthorized)
-            {
-                Log.Error("Not allowed to upload file", exc);
-                var message = String.Format("Not allowed to uplad file {0}", action.LocalFile.FullName);
-                StatusKeeper.SetFileState(action.LocalFile.FullName, FileStatus.Unchanged, FileOverlayStatus.Normal, "");
-                StatusNotification.NotifyChange(message, TraceLevel.Warning);
-                return true;
-            }
-            return false;
-        }
-
-        [Import]
-        public Selectives Selectives { get; set; }
-
-        public AsyncManualResetEvent UnpauseEvent { get; set; }
-    }
-}
+        private void ReportUploadProgress(string fileName, int block, int totalBlocks, long fileSize)\r
+        {\r
+            StatusNotification.Notify(totalBlocks == 0\r
+                                          ? new ProgressNotification(fileName, "Uploading", 1, 1, fileSize)\r
+                                          : new ProgressNotification(fileName, "Uploading", block, totalBlocks, fileSize));\r
+        }\r
+\r
+\r
+        private bool HandleUploadWebException(CloudAction action, WebException exc)\r
+        {\r
+            var response = exc.Response as HttpWebResponse;\r
+            if (response == null)\r
+                throw exc;\r
+            if (response.StatusCode == HttpStatusCode.Unauthorized)\r
+            {\r
+                Log.Error("Not allowed to upload file", exc);\r
+                var message = String.Format("Not allowed to uplad file {0}", action.LocalFile.FullName);\r
+                StatusKeeper.SetFileState(action.LocalFile.FullName, FileStatus.Unchanged, FileOverlayStatus.Normal, "");\r
+                StatusNotification.NotifyChange(message, TraceLevel.Warning);\r
+                return true;\r
+            }\r
+            return false;\r
+        }\r
+\r
+        [Import]\r
+        public Selectives Selectives { get; set; }\r
+\r
+        public AsyncManualResetEvent UnpauseEvent { get; set; }\r
+    }\r
+}\r
index 9cb7e1d..2f82498 100644 (file)
@@ -77,6 +77,31 @@ namespace Pithos.Network.Test
         }
 
 
+        [Test]
+        public void TestBlockRange()
+        {
+            var account = "--";
+            var apiKey = "--";
+
+            var client = new CloudFilesClient(account, apiKey)
+            {
+                AuthenticationUrl = @"https://pithos.dev.grnet.gr",
+                UsePithos = true
+            };
+
+            var blockSize = 4*1024*1024L;
+
+            long endBlock = 512*blockSize;
+            //ulong endBlokcL = 512*blockSize;
+
+            Assert.That(endBlock,Is.GreaterThan(0));
+/*
+            client.GetBlock(account,"Pithos",new Uri("somefile"),)
+            //var accountInfo = client.Authenticate();
+            var containers = client.ListContainers(accountInfo.UserName);
+            */
+        }
+
 
        
     }
index e9a9e6a..fe90121 100644 (file)
@@ -56,9 +56,9 @@ namespace Pithos.Network
     public class TreeHash
     {
         private const string DEFAULT_HASH_ALGORITHM = "sha256";
-        private const int DEFAULT_BLOCK_SIZE = 4*1024*1024;
+        private const long DEFAULT_BLOCK_SIZE = 4*1024*1024;
         public string BlockHash { get; set; }
-        public int BlockSize { get; set; }
+        public long BlockSize { get; set; }
         
         private long _bytes;
         public long Bytes