/// <summary> /// Unlocks the item in the remote storage. The item must implement <see cref="IVirtualLock"/> interface. /// </summary> /// <exception cref="ClientLockFailedException"> /// Thrown when a file can not be locked. For example when a lock-token file is blocked /// from another thread, during update, lock and unlock operations. /// </exception> public async Task UnlockAsync() { // Verify that the item supports locking. if (!(await GetItemAsync(userFileSystemPath) is IVirtualLock)) { throw new NotSupportedException(nameof(IVirtualLock)); } using (LockSync lockSync = await lockManager.LockAsync()) { await UnlockAsync(lockSync); } }
/// <summary> /// Locks the item in the remote storage. The item must implement <see cref="IVirtualLock"/> interface. /// </summary> /// <param name="lockSync">Sync lock.</param> /// <param name="lockMode">Indicates automatic or manual lock.</param> private async Task <ServerLockInfo> LockAsync(LockSync lockSync, LockMode lockMode) { ServerLockInfo lockInfo = null; try { logger.LogMessage("Locking in remote storage", userFileSystemPath); // Set lock-pending icon. await userFileSystemRawItem.SetLockPendingIconAsync(true); // Lock file in remote storage. IVirtualLock userLock = await GetItemAsync(userFileSystemPath) as IVirtualLock; lockInfo = await userLock.LockAsync(); // Save lock-token and lock-mode. await lockManager.SetLockInfoAsync(lockInfo); await lockManager.SetLockModeAsync(lockMode); logger.LogMessage("Locked in remote storage succesefully.", userFileSystemPath); } catch (Exception ex) { logger.LogError("Locking in remote storage failed.", userFileSystemPath, null, ex); // Delete lock-token and lock-mode files. await lockManager.DeleteLockAsync(); // Clear lock icon. await userFileSystemRawItem.SetLockInfoAsync(null); // Rethrow the exception preserving stack trace of the original exception. System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw(); } // Set locked icon and all lock properties. await userFileSystemRawItem.SetLockInfoAsync(lockInfo); return(lockInfo); }
/// <summary> /// Unlocks the file in the remote storage using existing <see cref="LockSync"/>. /// </summary> /// <param name="lockSync">Sync lock.</param> private async Task UnlockAsync(LockSync lockSync) { logger.LogMessage("Unlocking in remote storage", userFileSystemPath); // Set pending icon. await userFileSystemRawItem.SetLockPendingIconAsync(true); // Read lock-token from lock-info file. string lockToken = (await lockManager.GetLockInfoAsync()).LockToken; // Unlock file in remote storage. IVirtualLock userLock = await GetItemAsync(userFileSystemPath) as IVirtualLock; await userLock.UnlockAsync(lockToken); // Delete lock-mode and lock-token files. await lockManager.DeleteLockAsync(); // Remove lock icon. await userFileSystemRawItem.SetLockInfoAsync(null); logger.LogMessage("Unlocked in remote storage succesefully", userFileSystemPath); }
/// <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. } }