/// <summary>
        ///
        /// </summary>
        /// <param name="numberOfBytesToAdd"></param>
        /// <param name="numberOfBlocksCommitted"></param>
        /// <param name="allBlocksAcquired"></param>
        /// <param name="blocksToDistribute"></param>
        /// <exception cref="NoFreeBlocksException"></exception>
        private void PushFreeBlocksToAddressingSystem(int numberOfBytesToAdd, int numberOfBlocksCommitted, List <int> allBlocksAcquired, Stack <int> blocksToDistribute)
        {
            IntegerListConstrained lastSinglyIndirectBlock = null;
            int lastSingleIndirectBlockSize = 0;

            var addressingSystemBlockSizes =
                base.AddressingBlockSizesCalculator.GetSizesOfAddressingBlocksSufficientToStoreItems(numberOfBlocksCommitted);

            lastSingleIndirectBlockSize = addressingSystemBlockSizes.LastSingleIndirectBlockSize;

            if (this.CurrentSize != 0)
            {
                var lastSingleIndirectBlockIndex = base.DoubleIndirectBlocks[base.DoubleIndirectBlocks.Count - 1];

                lastSinglyIndirectBlock = new IntegerListConstrained(
                    base.Disk.ReadAllBytesFromBlock(lastSingleIndirectBlockIndex),
                    lastSingleIndirectBlockSize,
                    base.AddressingSystemParameters.DataBlockReferencesCountInSingleIndirectBlock);
            }

            try
            {
                while (blocksToDistribute.Count != 0)
                {
                    if ((lastSinglyIndirectBlock != null) && (!lastSinglyIndirectBlock.IsFull))
                    {
                        lastSinglyIndirectBlock.AddInteger(blocksToDistribute.Pop());
                    }
                    else
                    {
                        if (lastSinglyIndirectBlock != null)
                        {
                            base.Disk.WriteBytesToBlock(base.DoubleIndirectBlocks[base.DoubleIndirectBlocks.Count - 1],
                                                        lastSinglyIndirectBlock.ToByteArray());
                        }

                        int newBlockIndex = _freeBlockManager.AcquireFreeBlock();
                        allBlocksAcquired.Add(newBlockIndex);

                        base.DoubleIndirectBlocks.AddInteger(newBlockIndex);

                        base.Disk.WriteBytesToBlock(base.DataStreamDefinition.ContentsBlockIndex, base.DoubleIndirectBlocks.ToByteArray());

                        lastSinglyIndirectBlock = new IntegerListConstrained(new byte[0], 0, base.AddressingSystemParameters.DataBlockReferencesCountInSingleIndirectBlock);
                    }
                }

                base.Disk.WriteBytesToBlock(base.DoubleIndirectBlocks[base.DoubleIndirectBlocks.Count - 1], lastSinglyIndirectBlock.ToByteArray());
                base.DataStreamDefinition.StreamLengthInBytes += (numberOfBytesToAdd);
            }
            catch (NoFreeBlocksException)
            {
                _freeBlockManager.MarkBlocksAsFree(allBlocksAcquired);

                throw;
            }
        }
Beispiel #2
0
        public void MakeSureStructureBuilderAllocatesExactlyTheNumberOfBlocksNeededToStoreTheData()
        {
            var testCollaborators = TestCollaboratorsFactory.CreateCollaboratorsForTestingDataStreamStructureBuilder();

            MockRepository mocks = new MockRepository();

            IFreeBlockManager freeBlockManager = mocks.DynamicMock <IFreeBlockManager>();

            IFileSystemNodeStorage nodeStorageStub = mocks.Stub <IFileSystemNodeStorage>();

            int freeBlockCounter            = 25;
            int numberOfFreeBlocksAllocated = 0;

            using (mocks.Unordered())
            {
                Expect.Call(freeBlockManager.AcquireFreeBlocks(1)).IgnoreArguments().Do(
                    new Func <int, ReadOnlyCollection <int> >(delegate(int i)
                {
                    var blocks = new List <int>();

                    for (int j = 0; j < i; j++)
                    {
                        blocks.Add(freeBlockCounter);
                        freeBlockCounter++;
                    }

                    numberOfFreeBlocksAllocated += i;

                    return(blocks.AsReadOnly());
                }));

                Expect.Call(freeBlockManager.AcquireFreeBlock()).IgnoreArguments().Do(
                    new Func <int>(delegate
                {
                    freeBlockCounter++;
                    numberOfFreeBlocksAllocated++;
                    return(freeBlockCounter);
                }));
            }

            mocks.ReplayAll();

            var dataStreamStructureBuilder =
                new TestDataStreamStructureBuilder(
                    testCollaborators.FileNode.ResolvedNode.FileContentsStreamDefinition,
                    testCollaborators.Disk,
                    freeBlockManager,
                    nodeStorageStub,
                    testCollaborators.FileNode.ResolvedNode,
                    AddressingSystemParameters.Default);

            Assert.AreEqual(0, dataStreamStructureBuilder.DoubleIndirectBlocks.Count);

            dataStreamStructureBuilder.SetSize(1000);

            Assert.AreEqual(1000, dataStreamStructureBuilder.CurrentSize);

            var diskStructureEnumerator = dataStreamStructureBuilder.CreateEnumerator();

            Assert.AreEqual(2, numberOfFreeBlocksAllocated);   // один для данных, другой - под single indirect block

            Assert.AreEqual(1, diskStructureEnumerator.Count); // количество дисковых блоков = 1
            Assert.AreEqual(1, dataStreamStructureBuilder.DoubleIndirectBlocks.Count);

            dataStreamStructureBuilder.SetSize(1500);
            Assert.AreEqual(1500, dataStreamStructureBuilder.CurrentSize);

            dataStreamStructureBuilder.SetSize(2000);

            Assert.AreEqual(2000, dataStreamStructureBuilder.CurrentSize);

            diskStructureEnumerator = dataStreamStructureBuilder.CreateEnumerator();

            Assert.AreEqual(2, numberOfFreeBlocksAllocated);

            Assert.AreEqual(1, diskStructureEnumerator.Count); // количество дисковых блоков = 1
            Assert.AreEqual(1, dataStreamStructureBuilder.DoubleIndirectBlocks.Count);

            dataStreamStructureBuilder.SetSize(2048);
            Assert.AreEqual(2048, dataStreamStructureBuilder.CurrentSize);

            diskStructureEnumerator = dataStreamStructureBuilder.CreateEnumerator();

            Assert.AreEqual(2, numberOfFreeBlocksAllocated);   // оверхед системы адресации - еще один блок.

            Assert.AreEqual(1, diskStructureEnumerator.Count); // количество дисковых блоков = 2
            Assert.AreEqual(1, dataStreamStructureBuilder.DoubleIndirectBlocks.Count);

            dataStreamStructureBuilder.SetSize(testCollaborators.Disk.BlockSizeInBytes * (testCollaborators.Disk.BlockSizeInBytes / 4) * 3);

            Assert.AreEqual((testCollaborators.Disk.BlockSizeInBytes / 4) * 3 + 3, numberOfFreeBlocksAllocated);

            dataStreamStructureBuilder.SetSize(testCollaborators.Disk.BlockSizeInBytes * (testCollaborators.Disk.BlockSizeInBytes / 4) * 5);
        }