/// <summary> /// Moves the item in the remote storage. This method is called by the platform. /// To move item manually use the <see cref="MoveToAsync(string)"/> method instead. /// </summary> /// <param name="userFileSystemNewPath">Target path in user file system.</param> /// <param name="resultContext">Confirms move competeion. Passed by the platform only.</param> internal async Task MoveToAsync(string userFileSystemNewPath, IConfirmationResultContext resultContext) { // In this method you must either confirm or reject the move by calling call either // IConfirmationResultContext.ReturnConfirmationResult() or IConfirmationResultContext.ReturnErrorResult(). string userFileSystemOldPath = userFileSystemPath; try { if (!FsPath.IsRecycleBin(userFileSystemNewPath) && // When a file is deleted, it is moved to a Recycle Bin. !FsPath.AvoidSync(userFileSystemOldPath) && !FsPath.AvoidSync(userFileSystemNewPath)) { logger.LogMessage("Moving item in remote storage", userFileSystemOldPath, userFileSystemNewPath); /* * // Read In-Sync state before move and set after move. * if (FsPath.Exists(userFileSystemOldPath)) * { * inSync = PlaceholderItem.GetItem(userFileSystemOldPath).GetInSync(); * } */ IVirtualFileSystemItem userFileSystemItemOld = await GetItemAsync(userFileSystemOldPath); await userFileSystemItemOld.MoveToAsync(userFileSystemNewPath); //updateTargetOnSuccess = true; logger.LogMessage("Moved succesefully in remote storage", userFileSystemOldPath, userFileSystemNewPath); ETagManager eTagManager = virtualDrive.GetETagManager(userFileSystemOldPath); if (FsPath.Exists(eTagManager.ETagFilePath)) { await eTagManager.MoveToAsync(userFileSystemNewPath); logger.LogMessage("Moved ETag succesefully", userFileSystemOldPath, userFileSystemNewPath); } } // Confirm move. if (resultContext != null) { // Calling ReturnConfirmationResult() moves file in the user file system. logger.LogMessage("Confirming move in user file system", userFileSystemOldPath, userFileSystemNewPath); resultContext.ReturnConfirmationResult(); // After ReturnConfirmationResult() call the MoveToCompletionAsync() method is called. // After that, in case of a file, the file handle is closed, triggering IFile.CloseAsync() call // and Windows File Manager move progress window is closed. // In addition to thos, in case the target is the offline folder, the IFolder.GetChildrenAsync() method is called. } } catch (Exception ex) { logger.LogError("Failed to move item", userFileSystemOldPath, userFileSystemNewPath, ex); resultContext.ReturnErrorResult(); //string userFileSystemExPath = FsPath.Exists(userFileSystemNewPath) ? userFileSystemNewPath : userFileSystemOldPath; //await virtualDrive.GetUserFileSystemRawItem(userFileSystemExPath, logger).SetUploadErrorStateAsync(ex); } }
/// <inheritdoc/> public async Task <bool> DeleteAsync() { if (!FsPath.AvoidSync(userFileSystemPath)) { IVirtualFileSystemItem userFileSystemItem = await GetItemAsync(userFileSystemPath); await userFileSystemItem.DeleteAsync(); virtualDrive.GetETagManager(userFileSystemPath).DeleteETag(); return(true); } return(false); }
/// <summary> /// This is a strongly typed variant of GetVirtualFileSystemItemAsync() method for internal use. /// </summary> /// <typeparam name="T">This is either <see cref="IVirtualFile"/> or <see cref="IVirtualFolder"/>.</typeparam> /// <param name="userFileSystemPath">Path in user file system for which your will return a file or a folder.</param> /// <returns>File or folder object that corresponds to the path in user file system.</returns> internal async Task <T> GetItemAsync <T>(string userFileSystemPath, ILogger logger) where T : IVirtualFileSystemItem { FileSystemItemTypeEnum itemType = typeof(T).Name == nameof(IVirtualFile) ? FileSystemItemTypeEnum.File : FileSystemItemTypeEnum.Folder; IVirtualFileSystemItem userItem = await GetVirtualFileSystemItemAsync(userFileSystemPath, itemType, logger); if (userItem == null) { throw new System.IO.FileNotFoundException($"{itemType} not found.", userFileSystemPath); } if ((T)userItem == null) { throw new NotImplementedException($"{typeof(T).Name}"); } return((T)userItem); }
/// <inheritdoc/> public async Task UpdateAsync() { // This protects from ocationally calling update on moved items. if (PlaceholderItem.GetItem(userFileSystemPath).IsMoved()) { string originalPath = PlaceholderItem.GetItem(userFileSystemPath).GetOriginalPath(); throw new ConflictException(Modified.Client, $"The item was moved. Original path: {originalPath}"); } LockSync lockSync = null; try { if (!PlaceholderItem.GetItem(userFileSystemPath).GetInSync()) { // This will make sure only one thread can do the lock-update-unlock sequence. lockSync = await lockManager.LockAsync(); IVirtualFileSystemItem userFileSystemItem = await GetItemAsync(userFileSystemPath); ServerLockInfo lockInfo = null; if (userFileSystemItem is IVirtualLock) { // Get lock info in case of manual lock or failed lock/update/unlock if (await lockManager.IsLockedAsync()) { lockInfo = await lockManager.GetLockInfoAsync(); } // Lock file if auto-locking is enabled. else if (virtualDrive.Settings.AutoLock) { // Lock file in remote storage. lockInfo = await LockAsync(lockSync, LockMode.Auto); } } // Update item in remote storage. logger.LogMessage("Sending to remote storage", userFileSystemPath); await CreateOrUpdateAsync(FileMode.Open, lockInfo); //await new UserFileSystemRawItem(userFileSystemPath).ClearStateAsync(); logger.LogMessage("Sent to remote storage succesefully", userFileSystemPath); } // Unlock if auto-locked. if (await lockManager.GetLockModeAsync() == LockMode.Auto) { // Required in case the file failed to unlock during previous update. lockSync ??= await lockManager.LockAsync(); // Send unlock request to remote storage. await UnlockAsync(lockSync); } } catch (ClientLockFailedException ex) { // Failed to lock file. Possibly blocked from another thread. This is a normal behaviour. logger.LogMessage(ex.Message, userFileSystemPath); } catch (Exception ex) { // Some error when locking, updating or unlocking occured. await userFileSystemRawItem.SetUploadErrorStateAsync(ex); // Rethrow the exception preserving stack trace of the original exception. System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw(); } finally { if (lockSync != null) { lockSync.Dispose(); } // Do not delete lock-token and lock-mode files here, it is required if IUserLock // interfce is implemented and the file was locked manually. } }