/// <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);
            }
        }
Esempio n. 2
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;
        }
        /// <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;
        }
Esempio n. 4
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);
        }
        /// <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);
        }
Esempio n. 6
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);
        }
        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);
        }
Esempio n. 10
0
 public TestDataStreamStructureBuilder(DataStreamDefinition dataStreamDefinition, IVirtualDisk disk, IFreeBlockManager freeBlockManager, IFileSystemNodeStorage fileSystemNodeStorage, Node governingNode, AddressingSystemParameters addressingSystemParameters)
     : base(dataStreamDefinition, disk, freeBlockManager, fileSystemNodeStorage, governingNode, addressingSystemParameters)
 {
 }