#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);
}
}
}