#region /* ----------------------------------------------------------------------- * * * 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. * * ----------------------------------------------------------------------- */ #endregion using System; using System.Diagnostics.Contracts; using System.IO; using System.Threading; using Pithos.Interfaces; using Pithos.Network; namespace Pithos.Core.Agents { public enum CloudActionType { MustSynch, UploadUnconditional, DownloadUnconditional, DeleteLocal, DeleteCloud, RenameCloud, RenameLocal } public class CloudAction { public object Originator { get; set; } public AccountInfo AccountInfo { get; set; } public CloudActionType Action { 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 TreeHash { get; protected set; } //public Lazy TopHash { get; set; } [ContractInvariantMethod] private void Invariants() { Contract.Invariant(AccountInfo!=null); } public bool IsShared { get { return CloudFile!=null && AccountInfo.UserName != CloudFile.Account; } } protected CloudAction(AccountInfo accountInfo,CloudActionType action,object originator) { if (accountInfo==null) throw new ArgumentNullException("accountInfo"); Contract.EndContractBlock(); Action = action; AccountInfo = accountInfo; Originator = originator; } public CloudAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo localFile, ObjectInfo cloudFile, FileState state, int blockSize, string algorithm,object originator,CancellationToken token,IProgress progress ) : this(accountInfo,action,originator) { if(blockSize<=0) throw new ArgumentOutOfRangeException("blockSize"); Contract.EndContractBlock(); LocalFile = localFile.WithProperCapitalization(); CloudFile = cloudFile; FileState = state; if (LocalFile == null) return; TreeHash = new Lazy(() => Signature.CalculateTreeHash(LocalFile, blockSize,algorithm,1,token,progress), 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); } public 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()!=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].ToEscapedUri(); objectInfo=new ObjectInfo { Account = otherName, Container = otherContainer, Name = String.Join("/", otherParts.Splice(2)).ToEscapedUri() }; } 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(AccountInfo accountInfo, ObjectInfo cloudFile,object originator) :base(accountInfo,CloudActionType.DownloadUnconditional,originator) { if (cloudFile.Container==null) throw new ArgumentException("CloudFile.Container","cloudFile"); if (cloudFile.Container.IsAbsoluteUri) throw new ArgumentException("CloudFile.Container","cloudFile"); Contract.EndContractBlock(); CloudFile = cloudFile; } [ContractInvariantMethod] private void Invariants() { Contract.Invariant(CloudFile.Container!=null); Contract.Invariant(!CloudFile.Container.IsAbsoluteUri); } public override string ToString() { return String.Format("{0}: _ <- {1}", Action, CloudFile.Name); } } public class CloudDeleteAction:CloudAction { public CloudDeleteAction(AccountInfo accountInfo,FileSystemInfo fileInfo, FileState fileState,object originator) : this(accountInfo,fileInfo,CreateObjectInfoFor(accountInfo, fileInfo),fileState,originator) { } public CloudDeleteAction(AccountInfo accountInfo, FileSystemInfo fileInfo,ObjectInfo cloudFile, FileState fileState,object originator) : base(accountInfo,CloudActionType.DeleteCloud,originator) { CloudFile = cloudFile; LocalFile = fileInfo; FileState = fileState; } public CloudDeleteAction(CloudAction action) : this(action.AccountInfo,action.LocalFile,action.CloudFile,action.FileState,action) {} [ContractInvariantMethod] private void Invariants() { Contract.Invariant(CloudFile.Container != null); Contract.Invariant(!CloudFile.Container.IsAbsoluteUri); } public override string ToString() { return String.Format("{0}: _ ->{1}", Action, CloudFile.Name); } } public class CloudUploadAction:CloudAction { public bool IsCreation { get; set; } public CloudUploadAction(AccountInfo accountInfo, FileSystemInfo fileInfo, FileState state, int blockSize, string algorithm,object originator,bool isCreation,CancellationToken token,IProgress progress,TreeHash treeHash=null ) : base(accountInfo, CloudActionType.UploadUnconditional,fileInfo,CreateObjectInfoFor(accountInfo,fileInfo),state,blockSize,algorithm,originator,token,progress) { IsCreation = isCreation; if (treeHash != null) { TreeHash = new Lazy(() => treeHash); TreeHash.Force(); } } [ContractInvariantMethod] private void Invariants() { Contract.Invariant(CloudFile.Container != null); Contract.Invariant(!CloudFile.Container.IsAbsoluteUri); } } public class CloudMoveAction:CloudAction { public ObjectInfo OldCloudFile { get; set; } public FileSystemInfo OldLocalFile { get; set; } public CloudMoveAction(AccountInfo accountInfo, CloudActionType action, FileSystemInfo oldFile, FileSystemInfo newFile,object originator) :base(accountInfo,action,originator) { LocalFile = newFile; CloudFile = CreateObjectInfoFor(accountInfo, newFile); OldLocalFile = oldFile; OldCloudFile = CreateObjectInfoFor(accountInfo, oldFile); //This is a rename operation, a hash will not be used TreeHash = new Lazy(() => Network.TreeHash.Empty, LazyThreadSafetyMode.ExecutionAndPublication); } public override string ToString() { return String.Format("{0}:{1}->{2}", Action, OldCloudFile.Name, CloudFile.Name); } } }