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);
        }
Esempio n. 3
0
        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);
        }
Esempio n. 5
0
        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);
        }
Esempio n. 7
0
        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);
        }