/// <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);
        }
        /// <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);
        }
Beispiel #3
0
        /// <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);
        }
Beispiel #4
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);
        }