private static int WriteDiskHeaderTruncatingTheStream(Stream backingStream, int blockSizeInBytes, int maximumDiskSizeInBytes) { backingStream.SetLength(0); backingStream.Position = 0; // Всегда - Little Endian var binaryWriter = new BinaryWriter(backingStream, VirtualDisk.DataEncoding); binaryWriter.Write(VirtualDisk.DiskManufacturerId); binaryWriter.Write(VirtualDisk.DiskFirmwareVersion.ToString()); binaryWriter.Write(blockSizeInBytes); binaryWriter.Write(maximumDiskSizeInBytes); binaryWriter.Flush(); int totalHeaderLength = (int)backingStream.Length + sizeof(Int32); // +4 - нужно еще записать смещение первого блока относительно начала потока. int numberOfWholeBlocksOccupiedByHeader = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(totalHeaderLength, blockSizeInBytes); int firstBlockOffset = numberOfWholeBlocksOccupiedByHeader * blockSizeInBytes; binaryWriter.Write(numberOfWholeBlocksOccupiedByHeader * blockSizeInBytes); binaryWriter.BaseStream.SetLength(numberOfWholeBlocksOccupiedByHeader * blockSizeInBytes); binaryWriter.Flush(); return(firstBlockOffset); }
/// <summary> /// /// </summary> /// <param name="numberOfBytesToAdd"></param> /// <exception cref="NoFreeBlocksException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception> private void MakeLonger(int numberOfBytesToAdd) { int numberOfBlocksCommitted = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(base.CurrentSize, base.AddressingSystemParameters.BlockSize); int numberOfBlocksToAdd = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(base.CurrentSize + numberOfBytesToAdd, base.AddressingSystemParameters.BlockSize) - numberOfBlocksCommitted; if ((numberOfBlocksToAdd == 0) && (numberOfBytesToAdd > 0)) { base.DataStreamDefinition.StreamLengthInBytes += numberOfBytesToAdd; return; } else if (numberOfBlocksToAdd == 0) { return; } List <int> allBlocksAcquired = _freeBlockManager.AcquireFreeBlocks(numberOfBlocksToAdd).ToList(); var blocksToDistribute = new Stack <int>(allBlocksAcquired); PushFreeBlocksToAddressingSystem(numberOfBytesToAdd, numberOfBlocksCommitted, allBlocksAcquired, blocksToDistribute); }
public byte[] ReadMap(out int bitmapSizeInBits) { byte[] firstBlockBytes = _disk.ReadAllBytesFromBlock(_freeSpaceMapStartingBlock); var stream = new MemoryStream(firstBlockBytes); var binaryReader = new BinaryReader(stream); int freeSpaceLengthInBits = binaryReader.ReadInt32(); int freeSpaceLengthInBytes = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData( freeSpaceLengthInBits, Constants.NumberOfBitsInByte); ReadOnlyCollection <BucketDistribution> numberOfBytesToReadFromEachBlock = ItemDistributor.Distribute(freeSpaceLengthInBytes, _disk.BlockSizeInBytes - Constants.BlockReferenceSizeInBytes, _disk.BlockSizeInBytes); var freeSpaceMap = new byte[freeSpaceLengthInBytes]; int numberOfCurrentBlock = _freeSpaceMapStartingBlock; int initialArrayPosition = 0; foreach (BucketDistribution distribution in numberOfBytesToReadFromEachBlock) { byte[] newArray = _disk.ReadBytesFromBlock(numberOfCurrentBlock + distribution.BucketIndex, distribution.IndexOfFirstItemTheBucketGot, distribution.NumberOfItemsDistributed); Array.Copy(newArray, 0, freeSpaceMap, initialArrayPosition, distribution.NumberOfItemsDistributed); initialArrayPosition += distribution.NumberOfItemsDistributed; } bitmapSizeInBits = freeSpaceLengthInBits; return(freeSpaceMap); }
public void MakeSureWriteReadCycleWorksOnFreeSpaceMap() { Stream stream = new FileStream(@"e:\diskTests.tst", FileMode.Create); // new MemoryStream(); var disk = VirtualDisk.CreateFormattingTheStream(stream, 2048, 15000 * 2048); const int numberOfBlocksToMap = 150000; var mapBytes = new byte[numberOfBlocksToMap]; var bitArray = new BitArray(mapBytes); bitArray.Length = numberOfBlocksToMap; var freeBlockManager = new FreeBlockManagerBitArrayBased(bitArray, 22, numberOfBlocksToMap); freeBlockManager.AcquireFreeBlocks(7000); freeBlockManager.AcquireFreeBlocks(24); var bitmapStore = new FreeSpaceBitmapStore(disk, VirtualDiskFormatter.FreeSpaceStartingBlockIndex); var bytes = new byte[SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(numberOfBlocksToMap, Constants.NumberOfBitsInByte)]; bitArray.CopyTo(bytes, 0); bitmapStore.WriteMap(bytes, numberOfBlocksToMap); int bitmapSize; var bytesRead = bitmapStore.ReadMap(out bitmapSize); Assert.AreEqual(numberOfBlocksToMap, bitmapSize); CollectionAssert.AreEqual(bytes, bytesRead); }
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; }
public byte[] MapToByteArray() { var bufferForBitmapCopies = new byte[SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(_freeSpaceMapLength, Constants.NumberOfBitsInByte)]; _freeSpaceBitmap.CopyTo(bufferForBitmapCopies, 0); return(bufferForBitmapCopies); }
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); }
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); }
/// <summary> /// /// </summary> /// <param name="newLength"></param> /// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentOutOfRangeException"></exception> /// <exception cref="InconsistentDataDetectedException"></exception> /// <exception cref="ArgumentNullException"></exception> private void MakeShorter(int newLength) { int numberOfBlocksCommitted = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(base.CurrentSize, base.AddressingSystemParameters.BlockSize); int numberOfBlocksNeededToStoreNewData = SpaceRequirementsCalculator.GetNumberOfChunksNeededToStoreData(newLength, base.AddressingSystemParameters.BlockSize); int numberOfBlocksToRemove = numberOfBlocksCommitted - numberOfBlocksNeededToStoreNewData; if (numberOfBlocksToRemove == 0) //изменения в пределах одного блока. { base.DataStreamDefinition.StreamLengthInBytes = newLength; base.FileSystemNodeStorage.WriteNode(base.GoverningNode); return; } var oldAddressingSystemBlockSizes = base.AddressingBlockSizesCalculator.GetSizesOfAddressingBlocksSufficientToStoreItems(numberOfBlocksCommitted); var newAddressingSystemBlockSizes = base.AddressingBlockSizesCalculator.GetSizesOfAddressingBlocksSufficientToStoreItems(numberOfBlocksNeededToStoreNewData); int doubleIndirectBlockIndexToStopAt = newAddressingSystemBlockSizes.DoubleIndirectBlockSize == 0 ? 0 : newAddressingSystemBlockSizes.DoubleIndirectBlockSize; for (int i = oldAddressingSystemBlockSizes.DoubleIndirectBlockSize - 1; i >= doubleIndirectBlockIndexToStopAt; i--) { int singlyIndirectBlockIndex = base.DoubleIndirectBlocks[i]; int newSize; int currentSize; if (i == oldAddressingSystemBlockSizes.DoubleIndirectBlockSize - 1) { currentSize = oldAddressingSystemBlockSizes.LastSingleIndirectBlockSize; } else { currentSize = base.AddressingSystemParameters.DataBlockReferencesCountInSingleIndirectBlock; } if (i == doubleIndirectBlockIndexToStopAt) // ок, этот - остается. { newSize = newAddressingSystemBlockSizes.LastSingleIndirectBlockSize; } else { newSize = 0; } var listConstrained = new IntegerListConstrained(base.Disk.ReadAllBytesFromBlock(singlyIndirectBlockIndex), currentSize, base.AddressingSystemParameters.DataBlockReferencesCountInSingleIndirectBlock); _freeBlockManager.MarkBlocksAsFree(listConstrained.Shrink(newSize)); } _freeBlockManager.MarkBlocksAsFree(base.DoubleIndirectBlocks.Shrink(newAddressingSystemBlockSizes.DoubleIndirectBlockSize)); base.Disk.WriteBytesToBlock(base.DataStreamDefinition.ContentsBlockIndex, base.DoubleIndirectBlocks.ToByteArray()); base.DataStreamDefinition.StreamLengthInBytes = newLength; base.FileSystemNodeStorage.WriteNode(base.GoverningNode); }