+#region
+/* -----------------------------------------------------------------------
+ * <copyright file="CloudTransferAction.cs" company="GRNet">
+ *
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ * </copyright>
+ * -----------------------------------------------------------------------
+ */
+#endregion
using System;
+using System.Diagnostics.Contracts;
using System.IO;
using System.Threading;
using Pithos.Interfaces;
DownloadUnconditional,
DeleteLocal,
DeleteCloud,
- RenameCloud
+ RenameCloud,
+ RenameLocal
}
public class CloudAction
{
+ public AccountInfo AccountInfo { get; set; }
public CloudActionType Action { get; set; }
- public FileInfo LocalFile { get; set; }
+ public FileSystemInfo LocalFile { get; set; }
public ObjectInfo CloudFile { get; set; }
public FileState FileState { get; set; }
public string Container { get; set; }
+ public readonly DateTime Created = DateTime.Now;
- public Lazy<string> LocalHash { get; protected set; }
- private Lazy<string> _topHash;
- public Lazy<string> TopHash
+
+ public Lazy<TreeHash> TreeHash { get; protected set; }
+ //public Lazy<string> TopHash { get; set; }
+
+
+ [ContractInvariantMethod]
+ private void Invariants()
{
- get { return _topHash; }
- set { _topHash = value; }
+ Contract.Invariant(AccountInfo!=null);
}
+ public bool IsShared
+ {
+ get { return CloudFile!=null && AccountInfo.UserName != CloudFile.Account; }
+ }
- protected CloudAction(CloudActionType action)
+ protected CloudAction(AccountInfo accountInfo,CloudActionType action)
{
+ if (accountInfo==null)
+ throw new ArgumentNullException("accountInfo");
+ Contract.EndContractBlock();
+
Action = action;
+ AccountInfo = accountInfo;
}
- public CloudAction(CloudActionType action, FileInfo localFile, ObjectInfo cloudFile,FileState state,int blockSize, string algorithm) : this(action)
+ public CloudAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo localFile, ObjectInfo cloudFile, FileState state, int blockSize, string algorithm)
+ : this(accountInfo,action)
{
- LocalFile = localFile;
+ if(blockSize<=0)
+ throw new ArgumentOutOfRangeException("blockSize");
+ Contract.EndContractBlock();
+ LocalFile = localFile.WithProperCapitalization();
CloudFile = cloudFile;
FileState = state;
- if (LocalFile != null)
- {
- LocalHash = new Lazy<string>(() => LocalFile.CalculateHash(blockSize,algorithm),
- LazyThreadSafetyMode.ExecutionAndPublication);
- }
+
+ if (LocalFile == null)
+ return;
+
+ TreeHash = new Lazy<TreeHash>(() => Signature.CalculateTreeHash(LocalFile, blockSize,algorithm),
+ LazyThreadSafetyMode.ExecutionAndPublication);
}
+ //Calculate the download path for the cloud file
+ public string GetDownloadPath()
+ {
+ if (CloudFile == null)
+ return String.Empty;
+ var filePath = CloudFile.RelativeUrlToFilePath(AccountInfo.UserName);
+ return Path.Combine(AccountInfo.AccountPath, filePath);
+ }
+ public override string ToString()
+ {
+ return String.Format("{0}:{1}->{2}", Action, LocalFile.FullName, CloudFile.Name);
+ }
+ protected static ObjectInfo CreateObjectInfoFor(AccountInfo accountInfo, FileSystemInfo fileInfo)
+ {
+ if(accountInfo==null)
+ throw new ArgumentNullException("accountInfo");
+ if(fileInfo==null)
+ throw new ArgumentNullException("fileInfo");
+ Contract.Ensures(Contract.Result<ObjectInfo>()!=null);
+ Contract.EndContractBlock();
+
+ var capitalizedFileInfo = fileInfo.WithProperCapitalization();
+ var fullLocalName = capitalizedFileInfo.FullName;
+ var othersPath = Path.Combine(accountInfo.AccountPath, FolderConstants.OthersFolder);
+
+ ObjectInfo objectInfo;
+
+ var isShared = fullLocalName.StartsWith(othersPath, StringComparison.InvariantCultureIgnoreCase);
+ if (isShared)
+ {
+ var pathRelativeToOther = fullLocalName.Substring(othersPath.Length + 1);
+ var otherParts = pathRelativeToOther.Split('\\');
+ var otherName = otherParts[0];
+ var otherContainer = otherParts[1];
+ objectInfo=new ObjectInfo
+ {
+ Account = otherName,
+ Container = otherContainer,
+ Name = String.Join("/", otherParts.Splice(2))
+ };
+ }
+ else
+ objectInfo=new ObjectInfo(accountInfo.AccountPath, accountInfo.UserName, fileInfo);
+
+ objectInfo.Content_Type= (fileInfo is DirectoryInfo)
+ ? "appication/directory"
+ : "application/octet-stream";
+ return objectInfo;
+ }
}
public class CloudDownloadAction:CloudAction
{
- public CloudDownloadAction(ObjectInfo cloudFile)
- :base(CloudActionType.DownloadUnconditional)
+ 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}", Action, CloudFile.Name);
+ }
}
public class CloudDeleteAction:CloudAction
{
- public CloudDeleteAction(string fileName, FileState fileState)
- : this(new ObjectInfo { Name = fileName },fileState)
- {
+ public CloudDeleteAction(AccountInfo accountInfo,FileSystemInfo fileInfo, FileState fileState)
+ : this(accountInfo,fileInfo,CreateObjectInfoFor(accountInfo, fileInfo),fileState)
+ {
}
- public CloudDeleteAction(ObjectInfo cloudFile, FileState fileState)
- : base(CloudActionType.DeleteCloud)
+ public CloudDeleteAction(AccountInfo accountInfo, FileSystemInfo fileInfo,ObjectInfo cloudFile, FileState fileState)
+ : base(accountInfo,CloudActionType.DeleteCloud)
{
CloudFile = cloudFile;
+ LocalFile = fileInfo;
FileState = fileState;
}
+
+ public CloudDeleteAction(CloudAction action)
+ : this(action.AccountInfo,action.LocalFile,action.CloudFile,action.FileState)
+ {}
+
+ [ContractInvariantMethod]
+ private void Invariants()
+ {
+ Contract.Invariant(!String.IsNullOrWhiteSpace(CloudFile.Container));
+ }
+
+ public override string ToString()
+ {
+ return String.Format("{0}: _ ->{1}", Action, CloudFile.Name);
+ }
+
}
public class CloudUploadAction:CloudAction
{
- public CloudUploadAction(FileInfo fileInfo, FileState state, int blockSize, string algorithm)
- : base(CloudActionType.UploadUnconditional,fileInfo,ObjectInfo.Empty,state,blockSize,algorithm)
+ public CloudUploadAction(AccountInfo accountInfo, FileSystemInfo fileInfo, FileState state, int blockSize, string algorithm)
+ : base(accountInfo, CloudActionType.UploadUnconditional,fileInfo,CreateObjectInfoFor(accountInfo,fileInfo),state,blockSize,algorithm)
+ {
+ }
+
+ [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 CloudMoveAction(CloudActionType action, string oldPath, string oldFileName, string newFileName, string newPath)
- :base(action)
- {
- OldFileName = oldFileName;
- OldPath = oldPath;
- NewFileName = newFileName;
- NewPath = newPath;
+ public ObjectInfo OldCloudFile { get; set; }
+
+ public FileSystemInfo OldLocalFile { get; set; }
+
+ public CloudMoveAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo oldFile, FileSystemInfo newFile)
+ :base(accountInfo,action)
+ {
+ LocalFile = newFile;
+ CloudFile = CreateObjectInfoFor(accountInfo, newFile);
+
+ OldLocalFile = oldFile;
+ OldCloudFile = CreateObjectInfoFor(accountInfo, oldFile);
+
//This is a rename operation, a hash will not be used
- LocalHash = new Lazy<string>(() => String.Empty, LazyThreadSafetyMode.ExecutionAndPublication);
+ TreeHash = new Lazy<TreeHash>(() => Network.TreeHash.Empty, LazyThreadSafetyMode.ExecutionAndPublication);
}
+ public override string ToString()
+ {
+ return String.Format("{0}:{1}->{2}", Action, OldCloudFile.Name, CloudFile.Name);
+ }
}