+ catch (Exception exc)\r
+ {\r
+ //In case of error log and retry with the next poll\r
+ Log.ErrorFormat("[SYNC] Failed for file {0}. Will Retry.\r\n{1}",tuple.FilePath,exc);\r
+ }\r
+ }\r
+\r
+ private void DeleteLocalFile(FileAgent agent, string localFilePath)\r
+ {\r
+ StatusKeeper.SetFileState(localFilePath, FileStatus.Deleted,\r
+ FileOverlayStatus.Deleted, "");\r
+ using (NetworkGate.Acquire(localFilePath, NetworkOperation.Deleting))\r
+ {\r
+ agent.Delete(localFilePath);\r
+ }\r
+ //updateRecord(Remove C, L)\r
+ StatusKeeper.ClearFileStatus(localFilePath);\r
+ }\r
+\r
+ private async Task DownloadCloudFile(AccountInfo accountInfo, StateTuple tuple, CancellationToken token, string targetPath)\r
+ { \r
+ //Don't create a new state for non-existent files\r
+ if (File.Exists(targetPath) || Directory.Exists(targetPath))\r
+ StatusKeeper.SetFileState(targetPath, FileStatus.Modified, FileOverlayStatus.Modified,"");\r
+\r
+ var finalHash=await\r
+ NetworkAgent.Downloader.DownloadCloudFile(accountInfo, tuple.ObjectInfo, targetPath,\r
+ token)\r
+ .ConfigureAwait(false);\r
+ //updateRecord( L = S )\r
+ StatusKeeper.UpdateFileChecksum(targetPath, tuple.ObjectInfo.ETag,\r
+ finalHash);\r
+\r
+ StatusKeeper.StoreInfo(targetPath, tuple.ObjectInfo,finalHash);\r
+ }\r
+\r
+ private async Task UploadLocalFile(AccountInfo accountInfo, StateTuple tuple, CancellationToken token,\r
+ bool isUnselectedRootFolder, FileSystemInfo localInfo, HashSet<string> processedPaths, IProgress<HashProgress> progress)\r
+ {\r
+ var action = new CloudUploadAction(accountInfo, localInfo, tuple.FileState,\r
+ accountInfo.BlockSize, accountInfo.BlockHash,\r
+ "Poll", isUnselectedRootFolder, token, progress,tuple.Merkle); \r
+\r
+ using (StatusNotification.GetNotifier("Uploading {0}", "Uploaded {0}",true,\r
+ localInfo.Name))\r
+ {\r
+ await NetworkAgent.Uploader.UploadCloudFile(action, token).ConfigureAwait(false);\r
+ }\r
+\r
+ if (isUnselectedRootFolder)\r
+ {\r
+ var dirActions =(\r
+ from dir in ((DirectoryInfo) localInfo).EnumerateDirectories("*", SearchOption.AllDirectories)\r
+ let subAction = new CloudUploadAction(accountInfo, dir, null,\r
+ accountInfo.BlockSize, accountInfo.BlockHash,\r
+ "Poll", true, token, progress)\r
+ select subAction).ToList();\r
+ foreach (var dirAction in dirActions)\r
+ {\r
+ processedPaths.Add(dirAction.LocalFile.FullName);\r
+ }\r
+ \r
+ await TaskEx.WhenAll(dirActions.Select(a=>NetworkAgent.Uploader.UploadCloudFile(a,token)).ToArray());\r
+ }\r
+ }\r
+\r
+ private async Task<bool> MoveForLocalMove(AccountInfo accountInfo, StateTuple tuple)\r
+ {\r
+ //Is the previous path missing?\r
+ if (String.IsNullOrWhiteSpace(tuple.OldFullPath))\r
+ return false;\r
+ //Has the file locally, in which case it should be uploaded rather than moved?\r
+ if (tuple.OldChecksum != tuple.Merkle.TopHash.ToHashString())\r
+ return false;\r
+\r
+ var relativePath = tuple.ObjectInfo.RelativeUrlToFilePath(accountInfo.UserName);\r
+ var serverPath = Path.Combine(accountInfo.AccountPath, relativePath);\r
+ //Has the file been renamed on the server?\r
+ if (!tuple.OldFullPath.Equals(serverPath))\r
+ {\r
+ ReportConflictForDoubleRename(tuple.FilePath);\r
+ return false;\r
+ }\r
+\r
+ try\r
+ {\r
+\r
+ var client = new CloudFilesClient(accountInfo);\r
+ var objectInfo = CloudAction.CreateObjectInfoFor(accountInfo, tuple.FileInfo);\r
+ objectInfo.X_Object_Hash = tuple.Merkle.TopHash.ToHashString();\r
+ var containerPath = Path.Combine(accountInfo.AccountPath, objectInfo.Container.ToUnescapedString());\r
+ //TODO: SImplify these multiple conversions from and to Uris\r
+ var oldName = tuple.OldFullPath.AsRelativeTo(containerPath);\r
+ //Then execute a move instead of an upload\r
+ using (StatusNotification.GetNotifier("Moving {0}", "Moved {0}", true,tuple.FileInfo.Name))\r
+ {\r
+ await client.MoveObject(objectInfo.Account, objectInfo.Container, oldName.Replace('\\','/').ToEscapedUri(),\r
+ objectInfo.Container, objectInfo.Name).ConfigureAwait(false);\r
+ StatusKeeper.MoveFileState(tuple.OldFullPath, tuple.FilePath, objectInfo, tuple.Merkle);\r
+ //StatusKeeper.StoreInfo(tuple.FilePath,objectInfo,tuple.Merkle);\r
+ //StatusKeeper.ClearFolderStatus(tuple.FilePath);\r
+ }\r
+ return true;\r
+ }\r
+ catch (Exception exc)\r
+ {\r
+ Log.ErrorFormat("[MOVE] Failed for [{0}],:\r\n{1}", tuple.FilePath, exc);\r
+ //Return false to force an upload of the file\r
+ return false;\r
+ }\r
+\r
+ }\r
+\r
+ private void AddOwnFolderToSelectives(AccountInfo accountInfo, StateTuple tuple, string targetPath)\r
+ {\r
+ //Not for shared folders\r
+ if (tuple.ObjectInfo.IsShared==true)\r
+ return;\r
+ //Also ensure that any newly created folders are added to the selectives, if the original folder was selected\r
+ var containerPath = Path.Combine(accountInfo.AccountPath, tuple.ObjectInfo.Container.ToUnescapedString());\r
+\r
+ //If this is a root folder encountered for the first time\r
+ if (tuple.L == null && Directory.Exists(tuple.FileInfo.FullName) \r
+ && (tuple.FileInfo.FullName.IsAtOrBelow(containerPath)))\r
+ {\r
+ \r
+ var relativePath = tuple.ObjectInfo.RelativeUrlToFilePath(accountInfo.UserName);\r
+ var initialPath = Path.Combine(accountInfo.AccountPath, relativePath);\r
+\r
+ //var hasMoved = true;// !initialPath.Equals(targetPath);\r
+ //If the new path is under a selected folder, add it to the selectives as well\r
+ if (Selectives.IsSelected(accountInfo, initialPath))\r
+ {\r
+ Selectives.AddUri(accountInfo, tuple.ObjectInfo.Uri);\r
+ Selectives.Save(accountInfo);\r
+ }\r
+ }\r