/// <summary> /// Открывает указанный файл для записи и чтения. /// </summary> /// <param name="fullPathForFile">Путь, указывающий открываемый файл.</param> /// <returns>Поток данных файла, допускающий чтение и запись данных</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="FileNotFoundException"></exception> /// <exception cref="FileLockedException"></exception> /// <exception cref="ObjectDisposedException"></exception> public DataStreamReadableWritable OpenFileForWriting(string fullPathForFile) { MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFile, "fullPathForFile"); try { NodeWithSurroundingsResolvingResult <FileNode> nodeResolvingResult; DataStreamStructureBuilder dataStreamStructureBuilder = GetDataStreamStructureBuilderResolvingTheFile(fullPathForFile, out nodeResolvingResult); Guid lockId = _lockingManager.AcquireLock(nodeResolvingResult, LockKind.Write); var stream = new DataStream(dataStreamStructureBuilder, AddressingSystemParameters.Default.BlockSize, _lockingManager, lockId); var nodeUpdatingStream = new DataStreamNodeUpdating(stream, nodeResolvingResult.ResolvedNode, _fileSystemNodeStorage); return(nodeUpdatingStream); } catch (InvalidPathException) { throw new FileNotFoundException("Файл не найден по указанному пути (\"{0}\")".FormatWith(fullPathForFile)); } catch (CannotAcquireLockException) { throw new FileLockedException( "Не удалось открыть файл \"{0}\" с блокировкой на запись: он уже заблокирован на чтение или запись." .FormatWith(fullPathForFile)); } }
/// <summary> /// /// </summary> /// <param name="blockIndex"></param> /// <param name="dataStreamToAddReferenceIn"></param> /// <param name="nodeOwningTheStream"></param> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="InsufficientSpaceException"></exception> /// <exception cref="MaximumFileSizeReachedException"></exception> public void AddBlockReference(int blockIndex, DataStreamDefinition dataStreamToAddReferenceIn, Node nodeOwningTheStream) { if (dataStreamToAddReferenceIn == null) { throw new ArgumentNullException("dataStreamToAddReferenceIn"); } if (nodeOwningTheStream == null) { throw new ArgumentNullException("nodeOwningTheStream"); } MethodArgumentValidator.ThrowIfNegative(blockIndex, "blockIndex"); var streamStructureBuilder = new DataStreamStructureBuilder(dataStreamToAddReferenceIn, _virtualDisk, _freeBlockManager, _fileSystemNodeStorage, nodeOwningTheStream, AddressingSystemParameters.Default); // Note: никаких настоящих блокировок не использует. var parentFolderFileReferencesStream = new DataStream(streamStructureBuilder, AddressingSystemParameters.Default.BlockSize, new NullFileSystemObjectLockingManager(), Guid.NewGuid()); var nodeUpdatingStream = new DataStreamNodeUpdating(parentFolderFileReferencesStream, nodeOwningTheStream, _fileSystemNodeStorage); using (nodeUpdatingStream) { var stream = new MemoryStream(); var writer = new BinaryWriter(stream); writer.Write(blockIndex); nodeUpdatingStream.MoveToEnd(); nodeUpdatingStream.Write(stream.ToArray(), 0, (int)stream.Length); } }
/// <summary> /// /// </summary> /// <param name="folderToRemoveDirectoryFrom"></param> /// <param name="indexReferenceToRemove"></param> /// <param name="dataStreamBeingCorrected"></param> /// <exception cref="InconsistentDataDetectedException"></exception> public void TakeOutABlockFromBlockReferenceList(FolderNode folderToRemoveDirectoryFrom, int indexReferenceToRemove, DataStreamDefinition dataStreamBeingCorrected) { var streamStructureBuilder = new DataStreamStructureBuilder(dataStreamBeingCorrected, _virtualDisk, _freeBlockManager, _fileSystemNodeStorage, folderToRemoveDirectoryFrom, AddressingSystemParameters.Default); var lockingManager = new NullFileSystemObjectLockingManager(); var folderReferencesStream = new DataStream(streamStructureBuilder, AddressingSystemParameters.Default.BlockSize, lockingManager, Guid.NewGuid()); var nodeUpdatingStream = new DataStreamNodeUpdating(folderReferencesStream, folderToRemoveDirectoryFrom, _fileSystemNodeStorage); var referencesToBlocks = new byte[nodeUpdatingStream.Length]; nodeUpdatingStream.Read(referencesToBlocks, 0, nodeUpdatingStream.Length); var correctedStream = new MemoryStream(nodeUpdatingStream.Length); var reader = new BinaryReader(new MemoryStream(referencesToBlocks, true)); var writer = new BinaryWriter(correctedStream); int numberOfReferencesFound = 0; while (reader.BaseStream.Position != reader.BaseStream.Length) { int nodeIndex = reader.ReadInt32(); if (nodeIndex != indexReferenceToRemove) { writer.Write(nodeIndex); } else { numberOfReferencesFound++; } } if (numberOfReferencesFound != 1) { throw new InconsistentDataDetectedException("Обнаружены неконсистентные данные (произошла попытка удаления несуществующей ссылки на файл или папку). Возможна потеря данных. Обратитесь к разработчикам."); } nodeUpdatingStream.SetLength(nodeUpdatingStream.Length - Constants.BlockReferenceSizeInBytes); var bytes = correctedStream.ToArray(); nodeUpdatingStream.SetPosition(0); nodeUpdatingStream.Write(bytes, 0, bytes.Length); }