action.CloudFile.Name);
var localFile = action.LocalFile;
- var cloudFile = action.CloudFile;
- var downloadPath = (cloudFile == null)
- ? String.Empty
- : Path.Combine(accountInfo.AccountPath, cloudFile.RelativeUrlToFilePath(accountInfo.UserName));
+ var cloudFile = action.CloudFile;
+ var downloadPath = action.GetDownloadPath();
try
{
- var account = action.CloudFile.Account ?? accountInfo.UserName;
- var container = action.CloudFile.Container ?? FolderConstants.PithosContainer;
switch (action.Action)
{
case CloudActionType.UploadUnconditional:
- UploadCloudFile(accountInfo,account, container, localFile, action.LocalHash.Value, action.TopHash.Value);
+ UploadCloudFile(action);
break;
case CloudActionType.DownloadUnconditional:
- DownloadCloudFile(accountInfo, account, container, cloudFile,
- downloadPath);
+ DownloadCloudFile(accountInfo, cloudFile,downloadPath);
break;
case CloudActionType.DeleteCloud:
- DeleteCloudFile(accountInfo, account, container, cloudFile.Name);
+ DeleteCloudFile(accountInfo, cloudFile, cloudFile.Name);
break;
case CloudActionType.RenameCloud:
var moveAction = (CloudMoveAction)action;
- RenameCloudFile(accountInfo, account, container, moveAction.OldFileName, moveAction.NewPath,
- moveAction.NewFileName);
+ RenameCloudFile(accountInfo, cloudFile, moveAction);
break;
case CloudActionType.MustSynch:
if (!File.Exists(downloadPath))
{
- DownloadCloudFile(accountInfo, account, container, cloudFile, downloadPath);
+ DownloadCloudFile(accountInfo, cloudFile, downloadPath);
}
else
{
{
Log.ErrorFormat("{0} : {1} -> {2} failed because the file was not found.\n Rescheduling a delete",
action.Action, action.LocalFile, action.CloudFile, exc);
- Post(new CloudDeleteAction(accountInfo,action.CloudFile,action.FileState));
+ //Post a delete action for the missing file
+ Post(new CloudDeleteAction(action));
}
catch (Exception exc)
{
var cloudFile = action.CloudFile;
var downloadPath=action.LocalFile.FullName.ToLower();
- var account = cloudFile.Account;
- //Use "pithos" by default if no container is specified
- var container = cloudFile.Container ?? FolderConstants.PithosContainer;
-
- var cloudUri = new Uri(cloudFile.Name, UriKind.Relative);
var cloudHash = cloudFile.Hash.ToLower();
var localHash = action.LocalHash.Value.ToLower();
var topHash = action.TopHash.Value.ToLower();
if (lastUpTime <= lastLocalTime)
{
//It probably means it was changed while the app was down
- UploadCloudFile(accountInfo,account, container, localFile, action.LocalHash.Value,
- action.TopHash.Value);
+ UploadCloudFile(action);
}
else
{
{
case FileStatus.Unchanged:
//If the local file's status is Unchanged, we can go on and download the newer cloud file
- DownloadCloudFile(accountInfo,account, container,cloudFile,downloadPath);
+ DownloadCloudFile(accountInfo,cloudFile,downloadPath);
break;
case FileStatus.Modified:
//If the local file is Modified, we may have a conflict. In this case we should mark the file as Conflict
StatusNotification.NotifyChange(message, TraceLevel.Warning);
}
-/*
- private Task<object> Process(CloudMoveAction action)
- {
- if (action == null)
- throw new ArgumentNullException("action");
- Contract.EndContractBlock();
-
- Log.InfoFormat("[ACTION] Start Processing {0}:{1}->{2}", action.Action, action.LocalFile, action.CloudFile.Name);
-
- try
- {
- RenameCloudFile(action.OldFileName, action.NewPath, action.NewFileName);
- Log.InfoFormat("[ACTION] End Processing {0}:{1}->{2}", action.Action, action.LocalFile, action.CloudFile.Name);
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- catch (Exception exc)
- {
- Log.ErrorFormat("[REQUEUE] {0} : {1} -> {2} due to exception\r\n{3}",
- action.Action, action.OldFileName, action.NewFileName, exc);
-
- _agent.Post(action);
- }
- return CompletedTask<object>.Default;
- }
-*/
-
-
public void Post(CloudAction cloudAction)
{
if (cloudAction == null)
}
- private void RenameCloudFile(AccountInfo accountInfo,string account, string container,string oldFileName, string newPath, string newFileName)
+ private void RenameCloudFile(AccountInfo accountInfo,ObjectInfo cloudFile,CloudMoveAction action)
{
if (accountInfo==null)
throw new ArgumentNullException("accountInfo");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
- if (String.IsNullOrWhiteSpace(oldFileName))
- throw new ArgumentNullException("oldFileName");
- if (String.IsNullOrWhiteSpace(oldFileName))
- throw new ArgumentNullException("newPath");
- if (String.IsNullOrWhiteSpace(oldFileName))
- throw new ArgumentNullException("newFileName");
+ if (cloudFile==null)
+ throw new ArgumentNullException("cloudFile");
+ if (action==null)
+ throw new ArgumentNullException("action");
Contract.EndContractBlock();
//The local file is already renamed
- this.StatusKeeper.SetFileOverlayStatus(newPath, FileOverlayStatus.Modified);
+ this.StatusKeeper.SetFileOverlayStatus(action.NewPath, FileOverlayStatus.Modified);
+
+ var account = action.CloudFile.Account ?? accountInfo.UserName;
+ var container = action.CloudFile.Container ?? FolderConstants.PithosContainer;
+
var client = new CloudFilesClient(accountInfo);
- client.MoveObject(account, container, oldFileName, container, newFileName);
+ client.MoveObject(account, container, action.OldFileName, container, action.NewFileName);
- this.StatusKeeper.SetFileStatus(newPath, FileStatus.Unchanged);
- this.StatusKeeper.SetFileOverlayStatus(newPath, FileOverlayStatus.Normal);
- NativeMethods.RaiseChangeNotification(newPath);
+ this.StatusKeeper.SetFileStatus(action.NewPath, FileStatus.Unchanged);
+ this.StatusKeeper.SetFileOverlayStatus(action.NewPath, FileOverlayStatus.Normal);
+ NativeMethods.RaiseChangeNotification(action.NewPath);
}
- private void DeleteCloudFile(AccountInfo accountInfo, string account, string container, string fileName)
+ private void DeleteCloudFile(AccountInfo accountInfo, ObjectInfo cloudFile,string fileName)
{
if (accountInfo == null)
throw new ArgumentNullException("accountInfo");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
+ if (cloudFile==null)
+ throw new ArgumentNullException("cloudFile");
if (String.IsNullOrWhiteSpace(fileName))
throw new ArgumentNullException("fileName");
var fullPath = info.FullName.ToLower();
this.StatusKeeper.SetFileOverlayStatus(fullPath, FileOverlayStatus.Modified);
+ var account = cloudFile.Account ?? accountInfo.UserName;
+ var container = cloudFile.Container ?? FolderConstants.PithosContainer;
+
var client = new CloudFilesClient(accountInfo);
client.DeleteObject(account, container, fileName);
}
//Download a file.
- private void DownloadCloudFile(AccountInfo accountInfo, string account, string container,ObjectInfo cloudFile , string localPath)
+ private void DownloadCloudFile(AccountInfo accountInfo, ObjectInfo cloudFile , string localPath)
{
if (accountInfo == null)
throw new ArgumentNullException("accountInfo");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
if (cloudFile == null)
throw new ArgumentNullException("cloudFile");
+ if (String.IsNullOrWhiteSpace(cloudFile.Account))
+ throw new ArgumentNullException("cloudFile");
+ if (String.IsNullOrWhiteSpace(cloudFile.Container))
+ throw new ArgumentNullException("cloudFile");
if (String.IsNullOrWhiteSpace(localPath))
throw new ArgumentNullException("localPath");
if (!Path.IsPathRooted(localPath))
throw new ArgumentException("The localPath must be rooted", "localPath");
Contract.EndContractBlock();
- Debug.Assert(cloudFile.Account==account);
- Debug.Assert(cloudFile.Container == container);
-
- var download=Task.Factory.Iterate(DownloadIterator(accountInfo,account,container, cloudFile, localPath));
+ var download=Task.Factory.Iterate(DownloadIterator(accountInfo,cloudFile, localPath));
download.Wait();
}
- private IEnumerable<Task> DownloadIterator(AccountInfo accountInfo, string account, string container, ObjectInfo cloudFile, string localPath)
+ private IEnumerable<Task> DownloadIterator(AccountInfo accountInfo,ObjectInfo cloudFile, string localPath)
{
if (accountInfo == null)
throw new ArgumentNullException("accountInfo");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
- if (cloudFile==null)
+ if (cloudFile == null)
+ throw new ArgumentNullException("cloudFile");
+ if (String.IsNullOrWhiteSpace(cloudFile.Account))
+ throw new ArgumentNullException("cloudFile");
+ if (String.IsNullOrWhiteSpace(cloudFile.Container))
throw new ArgumentNullException("cloudFile");
if (String.IsNullOrWhiteSpace(localPath))
throw new ArgumentNullException("localPath");
//var hashPath = Path.Combine(FileAgent.FragmentsPath, relativePath + ".hashmap");
var client = new CloudFilesClient(accountInfo);
+ var account = cloudFile.Account;
+ var container = cloudFile.Container;
+
//Retrieve the hashmap from the server
var getHashMap = client.GetHashMap(account, container, url);
yield return getHashMap;
//If it's a small file
var downloadTask=(serverHash.Hashes.Count == 1 )
//Download it in one go
- ? DownloadEntireFile(accountInfo,client, account, container, relativeUrl, localPath,serverHash)
+ ? DownloadEntireFile(accountInfo,client, cloudFile, relativeUrl, localPath, serverHash)
//Otherwise download it block by block
- : DownloadWithBlocks(accountInfo,client, account, container, relativeUrl, localPath, serverHash);
+ : DownloadWithBlocks(accountInfo,client, cloudFile, relativeUrl, localPath, serverHash);
yield return downloadTask;
var attributes=File.GetAttributes(localPath);
File.SetAttributes(localPath,attributes|FileAttributes.ReadOnly);
}
- //Retrieve the object's metadata
- var info=client.GetObjectInfo(account, container, url);
- Debug.Assert(cloudFile==info);
- //And store it
- StatusKeeper.StoreInfo(localPath, info);
+
+ //Now we can store the object's metadata without worrying about ghost status entries
+ StatusKeeper.StoreInfo(localPath, cloudFile);
//Notify listeners that a local file has changed
StatusNotification.NotifyChangedFile(localPath);
}
//Download a small file with a single GET operation
- private Task DownloadEntireFile(AccountInfo accountInfo, CloudFilesClient client, string account, string container, Uri relativeUrl, string localPath,TreeHash serverHash)
+ private Task DownloadEntireFile(AccountInfo accountInfo, CloudFilesClient client, ObjectInfo cloudFile, Uri relativeUrl, string localPath,TreeHash serverHash)
{
if (client == null)
throw new ArgumentNullException("client");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
+ if (cloudFile==null)
+ throw new ArgumentNullException("cloudFile");
if (relativeUrl == null)
throw new ArgumentNullException("relativeUrl");
if (String.IsNullOrWhiteSpace(localPath))
Directory.CreateDirectory(tempFolder);
//Download the object to the temporary location
- var getObject = client.GetObject(account, container, relativeUrl.ToString(), tempPath).ContinueWith(t =>
+ var getObject = client.GetObject(cloudFile.Account, cloudFile.Container, relativeUrl.ToString(), tempPath).ContinueWith(t =>
{
t.PropagateExceptions();
//Create the local folder if it doesn't exist (necessary for shared objects)
}
//Download a file asynchronously using blocks
- public Task DownloadWithBlocks(AccountInfo accountInfo, CloudFilesClient client, string account, string container, Uri relativeUrl, string localPath, TreeHash serverHash)
+ public Task DownloadWithBlocks(AccountInfo accountInfo, CloudFilesClient client, ObjectInfo cloudFile, Uri relativeUrl, string localPath, TreeHash serverHash)
{
if (client == null)
throw new ArgumentNullException("client");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
+ if (cloudFile == null)
+ throw new ArgumentNullException("cloudFile");
if (relativeUrl == null)
throw new ArgumentNullException("relativeUrl");
if (String.IsNullOrWhiteSpace(localPath))
throw new ArgumentNullException("serverHash");
Contract.EndContractBlock();
- return Task.Factory.Iterate(BlockDownloadIterator(accountInfo,client,account,container, relativeUrl, localPath, serverHash));
+ return Task.Factory.Iterate(BlockDownloadIterator(accountInfo,client,cloudFile, relativeUrl, localPath, serverHash));
}
- private IEnumerable<Task> BlockDownloadIterator(AccountInfo accountInfo,CloudFilesClient client, string account, string container, Uri relativeUrl, string localPath, TreeHash serverHash)
+ private IEnumerable<Task> BlockDownloadIterator(AccountInfo accountInfo,CloudFilesClient client, ObjectInfo cloudFile, Uri relativeUrl, string localPath, TreeHash serverHash)
{
if (client == null)
throw new ArgumentNullException("client");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
+ if (cloudFile==null)
+ throw new ArgumentNullException("cloudFile");
if (relativeUrl == null)
throw new ArgumentNullException("relativeUrl");
if (String.IsNullOrWhiteSpace(localPath))
end= ((i + 1)*serverHash.BlockSize) ;
//Download the missing block
- var getBlock = client.GetBlock(account, container, relativeUrl, start, end);
+ var getBlock = client.GetBlock(cloudFile.Account, cloudFile.Container, relativeUrl, start, end);
yield return getBlock;
var block = getBlock.Result;
}
- private void UploadCloudFile(AccountInfo accountInfo, string account, string container, FileInfo fileInfo, string hash, string topHash)
+ private void UploadCloudFile(CloudAction action)
{
- if (accountInfo == null)
- throw new ArgumentNullException("accountInfo");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
- if (fileInfo == null)
- throw new ArgumentNullException("fileInfo");
- if (String.IsNullOrWhiteSpace(hash))
- throw new ArgumentNullException("hash");
- if (topHash == null)
- throw new ArgumentNullException("topHash");
+ if (action == null)
+ throw new ArgumentNullException("action");
Contract.EndContractBlock();
- var upload = Task.Factory.Iterate(UploadIterator(accountInfo,account,container,fileInfo, hash.ToLower(), topHash.ToLower()));
- upload.Wait();
+ try
+ {
+ var upload = Task.Factory.Iterate(UploadIterator(action));
+ upload.Wait();
+ }
+ catch (AggregateException ex)
+ {
+ var exc = ex.InnerException as WebException;
+ if (exc==null)
+ throw ex.InnerException;
+ 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;
+ }
+ throw;
+ }
}
- private IEnumerable<Task> UploadIterator(AccountInfo accountInfo, string account, string container, FileInfo fileInfo, string hash, string topHash)
+ private IEnumerable<Task> UploadIterator(CloudAction action)
{
- if (accountInfo == null)
- throw new ArgumentNullException("accountInfo");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
- if (fileInfo == null)
- throw new ArgumentNullException("fileInfo");
- if (String.IsNullOrWhiteSpace(hash))
- throw new ArgumentNullException("hash");
- if (topHash == null)
- throw new ArgumentNullException("topHash");
+ if (action == null)
+ throw new ArgumentNullException("action");
Contract.EndContractBlock();
+ var accountInfo=action.AccountInfo;
+
+ var fileInfo=action.LocalFile;
+
if (fileInfo.Extension.Equals("ignore", StringComparison.InvariantCultureIgnoreCase))
yield break;
-
+
+ var relativePath = fileInfo.AsRelativeTo(accountInfo.AccountPath);
+ if (relativePath.StartsWith(FolderConstants.OthersFolder))
+ {
+ var parts=relativePath.Split('\\');
+ var accountName = parts[1];
+ var oldName = accountInfo.UserName;
+ var absoluteUri = accountInfo.StorageUri.AbsoluteUri;
+ var nameIndex=absoluteUri.IndexOf(oldName);
+ 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
+ };
+ }
+
+
var url = fileInfo.AsRelativeUrlTo(accountInfo.AccountPath);
+
+
var fullFileName = fileInfo.FullName;
using(var gate=NetworkGate.Acquire(fullFileName,NetworkOperation.Uploading))
{
if (gate.Failed)
yield break;
+ var cloudFile = action.CloudFile;
+ var account = cloudFile.Account ?? accountInfo.UserName;
+ var container = cloudFile.Container ?? FolderConstants.PithosContainer;
+
var client = new CloudFilesClient(accountInfo);
//Even if GetObjectInfo times out, we can proceed with the upload
- var info = client.GetObjectInfo(account, container, url);
+ var info = client.GetObjectInfo(account, container, url);
var cloudHash = info.Hash.ToLower();
+ var hash = action.LocalHash.Value;
+ var topHash = action.TopHash.Value;
+
//If the file hashes match, abort the upload
if (hash == cloudHash || topHash ==cloudHash)
{
accountInfo.BlockHash);
yield return treeHash;
- yield return Task.Factory.Iterate(UploadWithHashMap(accountInfo,account,container,fileInfo,url,treeHash));
+ yield return Task.Factory.Iterate(UploadWithHashMap(accountInfo,cloudFile,fileInfo,url,treeHash));
}
else
StatusNotification.NotifyChangedFile(fullFileName);
}
- public IEnumerable<Task> UploadWithHashMap(AccountInfo accountInfo,string account,string container,FileInfo fileInfo,string url,Task<TreeHash> treeHash)
+ public IEnumerable<Task> UploadWithHashMap(AccountInfo accountInfo,ObjectInfo cloudFile,FileInfo fileInfo,string url,Task<TreeHash> treeHash)
{
if (accountInfo == null)
throw new ArgumentNullException("accountInfo");
- if (String.IsNullOrWhiteSpace(account))
- throw new ArgumentNullException("account");
- if (String.IsNullOrWhiteSpace(container))
- throw new ArgumentNullException("container");
+ if (cloudFile==null)
+ throw new ArgumentNullException("cloudFile");
if (fileInfo == null)
throw new ArgumentNullException("fileInfo");
if (String.IsNullOrWhiteSpace(url))
var fullFileName = fileInfo.FullName;
+ var account = cloudFile.Account ?? accountInfo.UserName;
+ var container = cloudFile.Container ?? FolderConstants.PithosContainer;
+
var client = new CloudFilesClient(accountInfo);
//Send the hashmap to the server
var hashPut = client.PutHashMap(account, container, url, treeHash.Result);