/// <summary>
        ///
        /// </summary>
        /// <param name="freeSpaceBitmap"></param>
        /// <param name="blockIndexOffset"></param>
        /// <param name="freeSpaceMapLength"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentException"></exception>
        public FreeBlockManagerBitArrayBased(BitArray freeSpaceBitmap, int blockIndexOffset, int freeSpaceMapLength)
        {
            MethodArgumentValidator.ThrowIfNull(freeSpaceBitmap, "freeSpaceBitmap");
            MethodArgumentValidator.ThrowIfNegative(blockIndexOffset, "blockIndexOffset");

            if (freeSpaceBitmap.Length != freeSpaceMapLength)
            {
                throw new ArgumentException("В Bitmap для разметки свободного места должно быть следующее число бит: {0}".FormatWith(freeSpaceMapLength));
            }

            _freeSpaceBitmap    = freeSpaceBitmap;
            _blockIndexOffset   = blockIndexOffset;
            _freeSpaceMapLength = freeSpaceMapLength;

            int freeBlocksCount = 0;

            for (int i = 0; i < freeSpaceBitmap.Length; i++)
            {
                if (!freeSpaceBitmap[i])
                {
                    freeBlocksCount++;
                }
            }

            _freeBlockCount = freeBlocksCount;
        }
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="InvalidOperationException"></exception>
        public void WriteBytes(byte[] array, int startingPosition, int length)
        {
            MethodArgumentValidator.ThrowIfNull(array, "array");
            MethodArgumentValidator.ThrowIfNegative(startingPosition, "startingPosition");
            MethodArgumentValidator.ThrowIfNegative(length, "length");

            if ((startingPosition + length) > array.Length)
            {
                throw new ArgumentException("В массиве, начиная с позиции {0}, не найдется следующего числа байт для записи: {1}".FormatWith(startingPosition, length));
            }

            if (this.IsAtEndOfBlock)
            {
                throw new InvalidOperationException("Запись за пределами границ блока не разрешена");
            }

            int positionAfterWriting = this.Position + length;

            if (positionAfterWriting > this.SizeInBytes)
            {
                throw new ArgumentException("Запись невозможна: попытка записи за пределами массива");
            }

            _disk.WriteBytesToBlock(BlockIndex, array, startingPosition, _position, length);

            if ((positionAfterWriting > this.OccupiedSpaceInBytes) && (this.OccupiedSpaceInBytes < this.SizeInBytes))
            {
                this.OccupiedSpaceInBytes += (positionAfterWriting - this.OccupiedSpaceInBytes);
            }

            this.Position = positionAfterWriting;
        }
        public FolderNode(string name, Guid id, int diskBlockIndex, int parentFolderBlockReference, DataStreamDefinition fileReferencesStreamDefinition, DataStreamDefinition folderReferencesStreamDefinition, DateTime creationTime, Guid version)
            : base(name, id, diskBlockIndex, version, creationTime)
        {
            MethodArgumentValidator.ThrowIfNull(fileReferencesStreamDefinition, "fileReferencesStream");
            MethodArgumentValidator.ThrowIfNull(folderReferencesStreamDefinition, "folderReferencesStream");
            MethodArgumentValidator.ThrowIfNegative(parentFolderBlockReference, "parentFolderBlockReference");
            MethodArgumentValidator.ThrowIfNegative(diskBlockIndex, "diskBlockIndex");
            MethodArgumentValidator.ThrowIfIsDefault(id, "id");

            _fileReferencesStreamDefinition   = fileReferencesStreamDefinition;
            _folderReferencesStreamDefinition = folderReferencesStreamDefinition;
            _parentFolderBlockReference       = parentFolderBlockReference;
        }
        public static bool ContainsLetters(this IEnumerable <char> characters)
        {
            MethodArgumentValidator.ThrowIfNull(characters, "characters");

            foreach (char character in characters)
            {
                if (Char.IsLetter(character))
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <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);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="blockIndex"></param>
        /// <param name="bytesToWrite"></param>
        /// <param name="arrayOffset"></param>
        /// <param name="blockOffset"></param>
        /// <param name="numberOfBytesToWrite"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public void WriteBytesToBlock(int blockIndex, byte[] bytesToWrite, int arrayOffset, int blockOffset, int numberOfBytesToWrite)
        {
            lock (_diskAccessCriticalSection)
            {
                ThrowIfDisposed();
                MethodArgumentValidator.ThrowIfNull(bytesToWrite, "bytesToWrite");
                MethodArgumentValidator.ThrowIfNegative(blockOffset, "blockOffset");
                MethodArgumentValidator.ThrowIfNegative(numberOfBytesToWrite, "numberOfBytesToWrite");
                MethodArgumentValidator.ThrowIfNegative(arrayOffset, "arrayOffset");

                this.MakeSureBlockIndexArgumentIsSane(blockIndex, "blockIndex");

                if (blockOffset >= this.BlockSizeInBytes)
                {
                    throw new ArgumentOutOfRangeException("blockOffset");
                }

                if (arrayOffset > bytesToWrite.Length)
                {
                    throw new ArgumentOutOfRangeException("arrayOffset");
                }

                if (numberOfBytesToWrite > this.BlockSizeInBytes)
                {
                    throw new ArgumentOutOfRangeException("numberOfBytesToWrite");
                }

                if ((blockOffset + numberOfBytesToWrite) > this.BlockSizeInBytes)
                {
                    throw new ArgumentOutOfRangeException("blockOffset, numberOfBytesToWrite");
                }

                if (bytesToWrite.Length < numberOfBytesToWrite)
                {
                    throw new ArgumentOutOfRangeException("numberOfBytesToWrite", "Массиве данных слишком мал, чтобы из него можно было считать следующее число байт: {0}.".FormatWith(numberOfBytesToWrite));
                }

                this.SeekToBlockStartWithInBlockOffset(blockIndex, blockOffset);

                _backingStream.Write(bytesToWrite, arrayOffset, numberOfBytesToWrite);
            }
        }
Exemple #7
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);
        }
        /// <summary>
        /// Note: case sensitive
        /// </summary>
        /// <param name="stringToCheck"></param>
        /// <param name="characters"></param>
        /// <param name="characterFound"></param>
        /// <returns></returns>
        public static bool ContainsAny(this string stringToCheck, IEnumerable <char> characters, out Nullable <char> characterFound)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(stringToCheck, "stringToCheck");
            MethodArgumentValidator.ThrowIfNull(characters, "characters");

            var charactersSeenSoFar  = new HashSet <char>();
            var charactersToCheckFor = new HashSet <char>(characters);

            foreach (char character in stringToCheck)
            {
                if (!charactersSeenSoFar.Contains(character) && charactersToCheckFor.Contains(character))
                {
                    characterFound = character;
                    return(true);
                }

                charactersSeenSoFar.Add(character);
            }

            characterFound = null;
            return(false);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="indexOfBlockToWriteTo"></param>
        /// <param name="bytesToWrite"></param>
        /// <param name="startingPosition"></param>
        /// <param name="numberOfBytesToWrite"></param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentException"></exception>
        private void WriteBytesToBlock(int indexOfBlockToWriteTo, byte[] bytesToWrite, int startingPosition, int numberOfBytesToWrite)
        {
            MethodArgumentValidator.ThrowIfNull(bytesToWrite, "bytesToWrite");
            MethodArgumentValidator.ThrowIfNegative(indexOfBlockToWriteTo, "indexOfBlockToWriteTo");
            MethodArgumentValidator.ThrowIfNegative(startingPosition, "startingPosition");
            MethodArgumentValidator.ThrowIfNegative(numberOfBytesToWrite, "numberOfBytesToWrite");

            if ((startingPosition + numberOfBytesToWrite) > bytesToWrite.Length)
            {
                throw new ArgumentException("Не получится записать {0} байтов, начиная с позиции {1}. В массиве всего следующее число байт: {2}.".FormatWith(numberOfBytesToWrite, startingPosition, bytesToWrite.Length));
            }

            if (bytesToWrite.Length > BlockSizeInBytes)
            {
                throw new ArgumentException("Невозможно записать данные в блок: в блок можно записать, максимум, {0} байт.".FormatWith(BlockSizeInBytes), "bytesToWrite");
            }

            this.MakeSureBlockIndexArgumentIsSane(indexOfBlockToWriteTo, "indexOfBlockToWriteTo");

            this.SeekToBlockStart(indexOfBlockToWriteTo);

            _backingStream.Write(bytesToWrite, startingPosition, numberOfBytesToWrite);
        }
        public static bool IsEmpty <T>(this IEnumerable <T> enumerable)
        {
            MethodArgumentValidator.ThrowIfNull(enumerable, "enumerable");

            return(!enumerable.Any());
        }