/// <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); } }
public NonEmptyDiskBlockEnumerator( IVirtualDisk disk, DataStreamDefinition dataStreamDefinition, AddressingSystemParameters addressingSystemParameters, IFileSystemNodeStorage fileSystemNodeStorage, Node streamOwningNode, EnumeratorAddressable <int> doubleIndirectListEnumerator) { if (disk == null) { throw new ArgumentNullException("disk"); } if (dataStreamDefinition == null) { throw new ArgumentNullException("dataStreamDefinition"); } if (addressingSystemParameters == null) { throw new ArgumentNullException("addressingSystemParameters"); } if (fileSystemNodeStorage == null) { throw new ArgumentNullException("fileSystemNodeStorage"); } if (streamOwningNode == null) { throw new ArgumentNullException("streamOwningNode"); } if (doubleIndirectListEnumerator == null) { throw new ArgumentNullException("doubleIndirectListEnumerator"); } _disk = disk; _dataStreamDefinition = dataStreamDefinition; _addressingSystemParameters = addressingSystemParameters; _fileSystemNodeStorage = fileSystemNodeStorage; _streamOwningNode = streamOwningNode; _doubleIndirectListEnumerator = doubleIndirectListEnumerator; if (doubleIndirectListEnumerator.Count == 0) { throw new ArgumentException("doubleIndirectListEnumerator"); } _numberOfBlocks = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(_dataStreamDefinition.StreamLengthInBytes, _disk.BlockSizeInBytes); _blockSizesCalculator = new AddressingBlockSizesCalculator(addressingSystemParameters.IndirectBlockReferencesCountInDoubleIndirectBlock, addressingSystemParameters.DataBlockReferencesCountInSingleIndirectBlock); _addressingSystemSizesOfLastBlocks = _blockSizesCalculator.GetSizesOfAddressingBlocksSufficientToStoreItems(_numberOfBlocks); this.SetFirstSingleIndirectBlock(); _current = new NullDiskBlock(); _position = PositionBeforeFirstElement; }
/// <summary> /// /// </summary> /// <param name="dataStreamDefinition"></param> /// <param name="disk"></param> /// <param name="freeBlockManager"></param> /// <param name="fileSystemNodeStorage"></param> /// <param name="governingNode"></param> /// <param name="addressingSystemParameters"></param> /// <exception cref="ArgumentNullException"></exception> public DataStreamStructureBuilder(DataStreamDefinition dataStreamDefinition, IVirtualDisk disk, IFreeBlockManager freeBlockManager, IFileSystemNodeStorage fileSystemNodeStorage, Node governingNode, AddressingSystemParameters addressingSystemParameters) : base(disk, dataStreamDefinition, addressingSystemParameters, fileSystemNodeStorage, governingNode) { if (freeBlockManager == null) { throw new ArgumentNullException("freeBlockManager"); } _freeBlockManager = freeBlockManager; }
public DataStreamStructureBuilderImmutable(IVirtualDisk disk, DataStreamDefinition dataStreamDefinition, AddressingSystemParameters addressingSystemParameters, IFileSystemNodeStorage fileSystemNodeStorage, Node governingNode) { if (disk == null) { throw new ArgumentNullException("disk"); } if (dataStreamDefinition == null) { throw new ArgumentNullException("dataStreamDefinition"); } if (addressingSystemParameters == null) { throw new ArgumentNullException("addressingSystemParameters"); } if (fileSystemNodeStorage == null) { throw new ArgumentNullException("fileSystemNodeStorage"); } if (governingNode == null) { throw new ArgumentNullException("governingNode"); } _disk = disk; _governingNode = governingNode; _fileSystemNodeStorage = fileSystemNodeStorage; _addressingSystemParameters = addressingSystemParameters; _dataStreamDefinition = dataStreamDefinition; int numberOfBlocks = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData( dataStreamDefinition.StreamLengthInBytes, addressingSystemParameters.BlockSize); _addressingBlockSizesCalculator = new AddressingBlockSizesCalculator(addressingSystemParameters.IndirectBlockReferencesCountInDoubleIndirectBlock, addressingSystemParameters.DataBlockReferencesCountInSingleIndirectBlock); _sizesOfLastAddressingBlocks = AddressingBlockSizesCalculator.GetSizesOfAddressingBlocksSufficientToStoreItems(numberOfBlocks); int doubleIndirectBlockSize = _sizesOfLastAddressingBlocks.DoubleIndirectBlockSize; _doubleIndirectBlocks = new IntegerListConstrained(disk.ReadAllBytesFromBlock(dataStreamDefinition.ContentsBlockIndex), doubleIndirectBlockSize, _addressingSystemParameters.IndirectBlockReferencesCountInDoubleIndirectBlock); CalculateAndSetMaximumSize(addressingSystemParameters); }
/// <summary> /// /// </summary> /// <param name="parentFolder"></param> /// <param name="newFolderName"></param> /// <returns></returns> /// <exception cref="InsufficientSpaceException"></exception> /// <exception cref="MaximumFileSizeReachedException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="FolderAlreadyExistsException"></exception> private FolderNode CreateFolder(FolderNode parentFolder, string newFolderName) { MethodArgumentValidator.ThrowIfNull(parentFolder, "parentFolder"); MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(newFolderName, "newFolderName"); var subfolders = _nodeResolver.GetAllFoldersFrom(parentFolder); var folderWithSameName = subfolders.FirstOrDefault(subfolder => _namesComparer.Equals(subfolder.Name, newFolderName)); if (folderWithSameName != null) { throw new FolderAlreadyExistsException("Подпапка с именем \"{0}\" уже существует в папке \"{1}\"".FormatWith(newFolderName, parentFolder.Name)); } var freeBlocks = _freeBlockManager.AcquireFreeBlocks(3); int blockToStoreFileReferencesIn = freeBlocks[0]; int blockToStoreFolderNodeIn = freeBlocks[1]; int blockToStoreSubfolderReferencesIn = freeBlocks[2]; var fileReferencesStreamDefinition = new DataStreamDefinition(blockToStoreFileReferencesIn, 0); var folderReferencesStreamDefinition = new DataStreamDefinition(blockToStoreSubfolderReferencesIn, 0); try { // Note: может стать последней каплей для переполненного диска, и тогда блоки придется отпустить _blockReferenceListsEditor.AddBlockReference(blockToStoreFolderNodeIn, parentFolder.FolderReferencesStreamDefinition, parentFolder); } catch (Exception) { _freeBlockManager.MarkBlocksAsFree(freeBlocks); throw; } var creationTime = DateTime.UtcNow; var newNode = new FolderNode(newFolderName, Guid.NewGuid(), blockToStoreFolderNodeIn, parentFolder.DiskBlockIndex, fileReferencesStreamDefinition, folderReferencesStreamDefinition, creationTime, Guid.NewGuid()); _fileSystemNodeStorage.WriteNode(newNode); return(newNode); }
/// <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); }
public void Format(IVirtualDisk virtualDisk, FileSystemNodeStorage fileSystemNodeStorage) { var numberOfBlocksToMap = virtualDisk.NumberOfBlocks - FileSystemHeaderReservedBlocks; int numberOfBytesNeededToStoreTheMap = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(numberOfBlocksToMap, Constants.NumberOfBitsInByte); int numberOfBlocksNeededToStoreTheMap = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(numberOfBytesNeededToStoreTheMap, virtualDisk.BlockSizeInBytes); numberOfBlocksToMap -= numberOfBlocksNeededToStoreTheMap; var freeSpaceBitmap = new BitArray(numberOfBytesNeededToStoreTheMap); freeSpaceBitmap.Length = numberOfBlocksToMap; var store = new FreeSpaceBitmapStore(virtualDisk, VirtualDiskFormatter.FreeSpaceStartingBlockIndex); var freeBlockManagerBitArrayBased = new FreeBlockManagerBitArrayBased(freeSpaceBitmap, FreeSpaceStartingBlockIndex + numberOfBlocksNeededToStoreTheMap, numberOfBlocksToMap); var freeBlockManager = new FreeBlockManagerDiskWriting(store, freeBlockManagerBitArrayBased); var freeBlocks = freeBlockManager.AcquireFreeBlocks(3); int rootBlockIndex = freeBlocks[0]; int rootFileReferencesBlock = freeBlocks[1]; int rootFolderReferencesBlock = freeBlocks[2]; var fileContentsStreamDefinition = new DataStreamDefinition(rootFileReferencesBlock, 0); var folderContentsStreamDefinition = new DataStreamDefinition(rootFolderReferencesBlock, 0); var rootNode = new FolderNode("root", Guid.NewGuid(), rootBlockIndex, 0, fileContentsStreamDefinition, folderContentsStreamDefinition, DateTime.UtcNow, Guid.NewGuid()); fileSystemNodeStorage.WriteNode(rootNode); fileSystemNodeStorage.WriteFileSystemHeader(new FileSystemHeader(rootBlockIndex, new Version(1, 0, 0, 0)), FileSystemHeaderBlockIndex); }
public DiskBlockNodeUpdating(IDiskBlock diskBlockWrapped, DataStreamDefinition owningStreamDefinition, Node blockOwningNode, IFileSystemNodeStorage fileSystemNodeStorage) { if (diskBlockWrapped == null) { throw new ArgumentNullException("diskBlockWrapped"); } if (owningStreamDefinition == null) { throw new ArgumentNullException("owningStreamDefinition"); } if (blockOwningNode == null) { throw new ArgumentNullException("blockOwningNode"); } if (fileSystemNodeStorage == null) { throw new ArgumentNullException("fileSystemNodeStorage"); } _diskBlockWrapped = diskBlockWrapped; _owningStreamDefinition = owningStreamDefinition; _blockOwningNode = blockOwningNode; _fileSystemNodeStorage = fileSystemNodeStorage; }
/// <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); }
public TestDataStreamStructureBuilder(DataStreamDefinition dataStreamDefinition, IVirtualDisk disk, IFreeBlockManager freeBlockManager, IFileSystemNodeStorage fileSystemNodeStorage, Node governingNode, AddressingSystemParameters addressingSystemParameters) : base(dataStreamDefinition, disk, freeBlockManager, fileSystemNodeStorage, governingNode, addressingSystemParameters) { }