/// <summary> /// /// </summary> /// <param name="fileToLock"></param> /// <param name="lockKind"></param> /// <returns></returns> /// <exception cref="CannotAcquireLockException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentException"></exception> public Guid AcquireLock(NodeWithSurroundingsResolvingResult <FileNode> fileToLock, LockKind lockKind) { if (fileToLock == null) { throw new ArgumentNullException("fileToLock"); } lock (_operationExecutionCriticalSection) { var idOfFileToLock = fileToLock.ResolvedNode.Id; FileLockable fileLockable; Guid newLockId; if (_fileIdsToLocks.ContainsKey(idOfFileToLock)) { fileLockable = _fileIdsToLocks[idOfFileToLock]; } else { fileLockable = new FileLockable(fileToLock.ResolvedNode, fileToLock.FoldersPassedWhileResolving); _fileIdsToLocks[idOfFileToLock] = fileLockable; } newLockId = LockTheFile(fileLockable, lockKind); ReportToAllFolderNodesLockableThatTheyHaveANewLock(fileToLock, fileLockable, newLockId); _lockIdsToLocks[newLockId] = fileLockable; return(newLockId); } }
/// <summary> /// /// </summary> /// <param name="fileLockable"></param> /// <param name="lockKind"></param> /// <returns></returns> /// <exception cref="ArgumentException"></exception> /// <exception cref="CannotAcquireLockException"></exception> private static Guid LockTheFile(FileLockable fileLockable, LockKind lockKind) { Guid newLockId; if (lockKind == LockKind.Read) { newLockId = fileLockable.LockForReading(); } else if (lockKind == LockKind.Write) { newLockId = fileLockable.LockForWriting(); } else { throw new ArgumentException("Вид блокировки {0} не поддерживается.".FormatWith(lockKind.ToString())); } return(newLockId); }
/// <summary> /// /// </summary> /// <param name="associatedFileLock"></param> /// <param name="lockId"></param> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="LockAlreadyHeldException"></exception> /// <exception cref="ArgumentException"></exception> public void AddLock(FileLockable associatedFileLock, Guid lockId) { if (associatedFileLock == null) { throw new ArgumentNullException("associatedFileLock"); } MethodArgumentValidator.ThrowIfIsDefault <Guid>(lockId, "lockId"); if (_idsOfAssociatedFileLocks.Contains(lockId)) { throw new LockAlreadyHeldException("Блокировка с идентификатором {0} уже привязана к блокировке папки.".FormatWith(associatedFileLock.FileId)); } if (!associatedFileLock.IdsOfParentFoldersUpToRoot.Contains(_idOfLockedNode)) { throw new ArgumentException("Папка (идентификатор - {0}) не содержится в списке зависимых для файловой блокировки, которую вы хотите связать с блокировкой этой папки.".FormatWith(_idOfLockedNode)); } _idsOfAssociatedFileLocks.Add(lockId); }
/// <summary> /// /// </summary> /// <param name="lockId"></param> /// <exception cref="ArgumentException"></exception> /// <exception cref="LockNotFoundException"></exception> public void ReleaseLock(Guid lockId) { MethodArgumentValidator.ThrowIfIsDefault <Guid>(lockId, "lockId"); lock (_operationExecutionCriticalSection) { if (_lockIdsToLocks.ContainsKey(lockId)) { FileLockable fileLockable = _lockIdsToLocks[lockId]; fileLockable.ReleaseLock(lockId); if (fileLockable.IsFreeForTaking) { _fileIdsToLocks.Remove(fileLockable.FileId); // все: файл разблокирован } // еще и все ветки отпускаем - если их больше ничто не держит. foreach (Guid nodeId in fileLockable.IdsOfParentFoldersUpToRoot) { FolderNodeLockable folderNodeLockable = _nodeIdsToLocks[nodeId]; folderNodeLockable.ReleaseLock(lockId); if (!folderNodeLockable.IsLocked) { _nodeIdsToLocks.Remove(folderNodeLockable.IdOfLockedNode); } } _lockIdsToLocks.Remove(lockId); } else { throw new LockNotFoundException("Не найдена блокировка с идентификатором {0}".FormatWith(lockId)); } } }
private void ReportToAllFolderNodesLockableThatTheyHaveANewLock(NodeWithSurroundingsResolvingResult <FileNode> fileToLock, FileLockable fileLockable, Guid newLockId) { foreach (FolderNode node in fileToLock.FoldersPassedWhileResolving) { FolderNodeLockable folderNodeLockableToAdjust; if (_nodeIdsToLocks.ContainsKey(node.Id)) { folderNodeLockableToAdjust = _nodeIdsToLocks[node.Id]; } else { folderNodeLockableToAdjust = new FolderNodeLockable(node); _nodeIdsToLocks[node.Id] = folderNodeLockableToAdjust; } folderNodeLockableToAdjust.AddLock(fileLockable, newLockId); } }