/// <exception cref="ArgumentNullException"></exception> /// <exception cref="FileAlreadyExistsException"></exception> /// <exception cref="NoFreeBlocksException"></exception> /// <exception cref="InsufficientSpaceException"></exception> /// <exception cref="MaximumFileSizeReachedException"></exception> private FileNode CreateFile(FolderNode parentFolder, string fileName) { MethodArgumentValidator.ThrowIfNull(parentFolder, "parentFolder"); MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fileName, "fileName"); var filesInTheFolder = _nodeResolver.GetAllFilesFrom(parentFolder); var fileWithSameName = filesInTheFolder.FirstOrDefault(file => _namesComparer.Equals(file.Name, fileName)); if (fileWithSameName != null) { throw new FileAlreadyExistsException("Файл с именем \"{0}\" уже существует в папке \"{1}\"".FormatWith(fileName, parentFolder.Name)); } var freeBlocks = _freeBlockManager.AcquireFreeBlocks(2); int blockToStoreDefinitionIn = freeBlocks[0]; int blockToStoreFileNodeIn = freeBlocks[1]; var fileContentsStreamDefinition = new DataStreamDefinition(blockToStoreDefinitionIn, 0); try { // Note: это добавление ссылки может стать последней каплей для заполненного диска, тогда блоки придется отпустить _blockReferenceListsEditor.AddBlockReference(blockToStoreFileNodeIn, parentFolder.FileReferencesStreamDefinition, parentFolder); } catch (Exception) { _freeBlockManager.MarkBlocksAsFree(freeBlocks); throw; } var creationTime = DateTime.UtcNow; var fileNode = new FileNode(fileName, Guid.NewGuid(), blockToStoreFileNodeIn, fileContentsStreamDefinition, creationTime, creationTime, Guid.NewGuid()); _fileSystemNodeStorage.WriteNode(fileNode); return(fileNode); }
/// <summary> /// Перемещает папку в указанную директорию. /// </summary> /// <param name="currentPathForFolder">Полный путь (от корня) к папке, которую следует переместить.</param> /// <param name="pathToFolderThatWillContainTheFolderMoved">Полный путь к папке, в которую нужно переместить указанную директорию (<paramref name="currentPathForFolder"/>).</param> /// <returns>Описание перемещенной папки, взятое с учетом ее нового местоположения.</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="FolderLockedException"></exception> /// <exception cref="FolderAlreadyExistsException"></exception> /// <exception cref="FolderNotFoundException"></exception> /// <exception cref="MaximumFolderCountReachedException"></exception> /// <exception cref="InsufficientSpaceException"></exception> /// <exception cref="InvalidOperationException">Если пытаетесь переместить папку в одну из ее собственных поддиректорий.</exception> public FolderInfo MoveFolder(string currentPathForFolder, string pathToFolderThatWillContainTheFolderMoved) { MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(currentPathForFolder, "cucurrentPathForFolderrrentPathForFile"); MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(pathToFolderThatWillContainTheFolderMoved, "pathToFolderThatWillContainTheFolderMoved"); try { var newParentNodeResolvingResult = _nodeResolver.ResolveFolderNodeByPath(pathToFolderThatWillContainTheFolderMoved); FolderNode foldersNewHome = newParentNodeResolvingResult.ResolvedNode; string folderName; var currentParentFolder = _nodeResolver.ResolveParentFolderNodeByPath(currentPathForFolder, out folderName); FolderNode folderToRemoveDirectoryFrom = currentParentFolder.ResolvedNode; var directoriesInFolder = _nodeResolver.GetAllFoldersFrom(folderToRemoveDirectoryFrom); FolderNode folderToMove = directoriesInFolder.FirstOrDefault(fileNode => _namesComparer.Equals(fileNode.Name, folderName)); if (folderToMove == null) { throw new FolderNotFoundException("Не найдена папка для перемещения (\"{0}\")".FormatWith(currentPathForFolder)); } if (newParentNodeResolvingResult.FoldersPassedWhileResolving.Any(folderNode => folderNode.Id.Equals(folderToMove.Id))) { throw new InvalidOperationException("Операция перемещения папки \"{0}\" в \"{1}\" отменена: невозможно переместить папку в одну из ее же поддиректорий.".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved)); } if (_lockingManager.IsNodeLockedForRenamesAndMoves(folderToMove)) { throw new FolderLockedException("Не удалось переместить папку (\"{0}\"): она или любая из ее поддиректорий содержит файлы открытые сейчас для чтения или записи.".FormatWith(currentPathForFolder)); } var allSubfoldersOfDestinationFolder = _nodeResolver.GetAllFoldersFrom(foldersNewHome); var idsOfAllSubfolders = _nodeResolver.GetIdsOfAllFoldersUnderGivenOne(currentPathForFolder); // перемещение в то место, где файл и так уже находится.) if (newParentNodeResolvingResult.ResolvedNode.Id.Equals(currentParentFolder.ResolvedNode.Id)) { return(new FolderInfo(allSubfoldersOfDestinationFolder.First(fileNode => _namesComparer.Equals(fileNode.Name, folderName)), currentPathForFolder)); } if (allSubfoldersOfDestinationFolder.Any(fileNode => _namesComparer.Equals(fileNode.Name, folderName))) { throw new FolderAlreadyExistsException("Перемещение папки невозможно: в директории \"{0}\" уже существует папка с именем \"{1}\"".FormatWith(pathToFolderThatWillContainTheFolderMoved, folderName)); } // сначала добавляем ссылку в новую папку, потом удаляем ссылку из старой (на добавление может не хватить места, удалить же можно всегда). _blockReferenceListsEditor.AddBlockReference(folderToMove.DiskBlockIndex, foldersNewHome.FolderReferencesStreamDefinition, foldersNewHome); // TODO: поглядеть на исключения этого метода. _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveDirectoryFrom, folderToMove.DiskBlockIndex, folderToRemoveDirectoryFrom.FolderReferencesStreamDefinition); _folderEnumeratorRegistry.InvalidateEnumeratorsFor(newParentNodeResolvingResult.FoldersPassedWhileResolving); _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(newParentNodeResolvingResult.ResolvedNode.Id); _folderEnumeratorRegistry.InvalidateEnumeratorsFor(currentParentFolder.FoldersPassedWhileResolving); _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(currentParentFolder.ResolvedNode.Id); _folderEnumeratorRegistry.InvalidateEnumeratorsFor(idsOfAllSubfolders); allSubfoldersOfDestinationFolder = _nodeResolver.GetAllFoldersFrom(foldersNewHome); return(new FolderInfo( allSubfoldersOfDestinationFolder.Single(folderNode => _namesComparer.Equals(folderNode.Name, folderName)), _pathBuilder.CombinePaths(pathToFolderThatWillContainTheFolderMoved, folderName))); } catch (InsufficientSpaceException) { throw new InsufficientSpaceException("Не удалось переместить папку из \"{0}\" в \"{1}\" - не хватает места на диске для проведения операции.".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved)); } catch (MaximumFileSizeReachedException) { throw new MaximumFolderCountReachedException("Не удалось переместить папку \"{0}\". Папка \"{1}\" не может вместить больше файлов, чем уже вмещает".FormatWith(currentPathForFolder, pathToFolderThatWillContainTheFolderMoved)); } catch (CannotResolvePathException exception) { throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message)); } catch (InvalidPathException exception) { throw new FolderNotFoundException("Не удалось найти папку, где находится перемещаемый файл, или папку, в которую его следует переместить. {0}".FormatWith(exception.Message)); } }