/// <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;
        }
示例#2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="fileSystem"></param>
        /// <param name="exportingFolderPath"></param>
        /// <param name="virtualDestinationFolder"></param>
        /// <param name="taskToken"></param>
        /// <returns></returns>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="CannotGetImportedFolderStructureException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        internal static ReadOnlyCollection <FileSystemTaskResult> ImportFolderFromRealFileSystem(
            this VirtualFileSystem fileSystem,
            string exportingFolderPath,
            string virtualDestinationFolder,
            IFileSystemCancellableTaskToken taskToken)
        {
            if (fileSystem == null)
            {
                throw new ArgumentNullException("fileSystem");
            }
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(exportingFolderPath, "exportingFolderPath");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(virtualDestinationFolder, "virtualDestinationFolder");

            FolderAddressable folderAddressable = CreateFileSystemObjectStructureFromFolder(exportingFolderPath);

            int totalNumberOfFilesToTraverse = folderAddressable.GetTotalFileCount();

            // Note: можно уменьшить связность классов, передав сюда через интерфейс фабрику, которая уж знает, как сделать нужного Visitor-а.

            ImportingAddressableObjectVisitor visitor = new ImportingAddressableObjectVisitor(fileSystem, exportingFolderPath, virtualDestinationFolder,
                                                                                              new RealFileContentsBufferFactory(), taskToken, totalNumberOfFilesToTraverse);

            if (!fileSystem.FolderExists(virtualDestinationFolder))
            {
                throw new FolderNotFoundException("Не удалось найти папку \"{0}\", в которую следует произвести копирование/импорт.".FormatWith(virtualDestinationFolder));
            }

            folderAddressable.Accept(visitor);
            var results = visitor.GetResult();

            return(results);
        }
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public DiskBlock(IVirtualDisk disk, int index, int occupiedSpaceInBytes, int position)
        {
            if (disk == null)
            {
                throw new ArgumentNullException("disk");
            }

            MethodArgumentValidator.ThrowIfNegative(index, "index");
            MethodArgumentValidator.ThrowIfNegative(occupiedSpaceInBytes, "occupiedSpaceInBytes");
            MethodArgumentValidator.ThrowIfNegative(position, "position");

            if (index >= disk.NumberOfBlocks)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            if (occupiedSpaceInBytes > disk.BlockSizeInBytes)
            {
                throw new ArgumentOutOfRangeException("occupiedSpaceInBytes");
            }

            if (position > disk.BlockSizeInBytes)
            {
                throw new ArgumentOutOfRangeException("position");
            }

            _disk       = disk;
            _blockIndex = index;
            this.OccupiedSpaceInBytes = occupiedSpaceInBytes;
            this.SizeInBytes          = _disk.BlockSizeInBytes;
            _position = position;
        }
        /// <summary>
        /// Устанавливает указатель текущего положения в потоке в новое место.
        /// Примечание: за границу потока установить указатель нельзя (допускается лишь устанавливать ее за последним записанным/считанным байтом).
        /// </summary>
        /// <param name="newPosition">Новая позиция указателя текущего положения.</param>
        /// <exception cref="InvalidOperationException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public override void SetPosition(int newPosition)
        {
            lock (_stateChangeCriticalSection)
            {
                this.ThrowIfDisposed();

                MethodArgumentValidator.ThrowIfNegative(newPosition, "newPosition");

                if (newPosition > this.Length)
                {
                    throw new ArgumentOutOfRangeException("newPosition", "Невозможно установить позицию за пределами потока данных.");
                }

                if (newPosition == this.Length)
                {
                    this.MoveToEnd();
                    return;
                }

                int blockIndex = newPosition / _blockSize;

                _diskBlockEnumerator.SetPosition(blockIndex);
                _diskBlockEnumerator.Current.Position = newPosition % _blockSize;
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="newSize"></param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="NoFreeBlocksException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="InconsistentDataDetectedException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="MaximumFileSizeReachedException"></exception>
        public override void SetSize(int newSize)
        {
            MethodArgumentValidator.ThrowIfNegative(newSize, "newSize");

            if (newSize == this.CurrentSize)
            {
                return;
            }

            if (newSize > this.MaximumSize)
            {
                throw new MaximumFileSizeReachedException(
                          "Не удалось установить размер структуры в {0} байт. Максимальный размер - {1} байт.".FormatWith(
                              newSize, this.MaximumSize));
            }

            if (newSize > this.CurrentSize)
            {
                this.MakeLonger(newSize - this.CurrentSize);
            }
            else
            {
                this.MakeShorter(newSize);
            }
        }
        /// <summary>
        /// Устанавливает длину потока (беря себе или освобождая соответствующий объем дискового пространства).
        /// </summary>
        /// <param name="newLength">Новая длина потока</param>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public override void SetLength(int newLength)
        {
            lock (_stateChangeCriticalSection)
            {
                this.ThrowIfDisposed();

                MethodArgumentValidator.ThrowIfNegative(newLength, "newLength");

                if (newLength < _streamStructureBuilder.CurrentSize)
                {
                    this.Shrink(newLength);
                    return;
                }

                if (newLength == this.Length)
                {
                    return;
                }

                int position = this.Position;

                this.MoveToEnd();

                int numberOfZeroesToAdd = this.Length == 0
                                              ? newLength
                                              : newLength - (_streamStructureBuilder.CurrentSize - 1);

                WriteZeroes(numberOfZeroesToAdd);

                this.SetPosition(position);
            }
        }
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentException"></exception>
        internal DataStream(
            IDataStreamStructureBuilder streamStructureBuilder,
            int blockSize,
            IFileSystemLockReleaseManager lockingManager,
            Guid idOfLockBeingHeld)
        {
            try
            {
                if (streamStructureBuilder == null)
                {
                    throw new ArgumentNullException("streamStructureBuilder");
                }
                if (lockingManager == null)
                {
                    throw new ArgumentNullException("lockingManager");
                }
                MethodArgumentValidator.ThrowIfIsDefault(idOfLockBeingHeld, "idOfLockBeingHeld");
                MethodArgumentValidator.ThrowIfNegative(blockSize, "blockSize");

                _streamStructureBuilder = streamStructureBuilder;
                _blockSize           = blockSize;
                _lockingManager      = lockingManager;
                _idOfLockBeingHeld   = idOfLockBeingHeld;
                _diskBlockEnumerator = streamStructureBuilder.CreateEnumerator();
            }
            catch (Exception)
            {
                GC.SuppressFinalize(this);

                throw;
            }
        }
示例#8
0
        /// <summary>
        /// Создает Iterator для перебора файлов в папке, имена которых удовлетворяют заданной маске (<paramref name="patternNamesOfFilesMustMatch"/>).
        /// Работает рекурсивно - то есть перебирает и файлы во всех подпапках указанной папки.
        /// Note: генерирует исключение (<see cref="InvalidOperationException"/>), если папка, по которой производится обход, меняется во время обхода (итераторы не thread-safe, я бы их лучше не показывал, но это явно зафиксированное требования).
        /// </summary>
        /// <param name="folderToEnumerateFilesIn">Папка, в которой следует искать файлы.</param>
        /// <param name="patternNamesOfFilesMustMatch">Маска для поиска файлов. Звездочка означает любую последовательность символов. Знак вопроса - один любой символ.</param>
        /// <returns>Iterator для перебора файлов в папке, имена которых удовлетворяют заданной маске (<paramref name="patternNamesOfFilesMustMatch"/>)</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public IEnumerator <FileInfo> EnumerateFilesUnderFolder(string folderToEnumerateFilesIn, string patternNamesOfFilesMustMatch)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(folderToEnumerateFilesIn, "folderToEnumerateFilesIn");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(patternNamesOfFilesMustMatch, "patternNamesOfFilesMustMatch");

            Monitor.Enter(_operationExecutionCriticalSection);

            try
            {
                ThrowIfDisposed();

                var nodeResolvingResult = _nodeResolver.ResolveFolderNodeByPath(folderToEnumerateFilesIn);

                var folder = new FolderInfo(nodeResolvingResult.ResolvedNode, folderToEnumerateFilesIn);

                var enumerator = new FolderContentsEnumerator(folder, patternNamesOfFilesMustMatch, _folderEnumeratorRegistry, this);
                _folderEnumeratorRegistry.RegisterEnumerator(enumerator);

                return(enumerator);
            }
            catch (InvalidPathException)
            {
                throw new FolderNotFoundException(
                          "Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(folderToEnumerateFilesIn));
            }
            finally
            {
                Monitor.Exit(_operationExecutionCriticalSection);
            }
        }
示例#9
0
        /// <summary>
        /// Открывает указанный файл для записи и чтения.
        /// </summary>
        /// <param name="fullPathForFile">Путь, указывающий открываемый файл.</param>
        /// <returns>Поток данных файла, допускающий чтение и запись данных</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="FileLockedException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public DataStreamReadableWritable OpenFileForWriting(string fullPathForFile)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFile, "fullPathForFile");

            try
            {
                NodeWithSurroundingsResolvingResult <FileNode> nodeResolvingResult;
                DataStreamStructureBuilder dataStreamStructureBuilder = GetDataStreamStructureBuilderResolvingTheFile(fullPathForFile, out nodeResolvingResult);

                Guid lockId = _lockingManager.AcquireLock(nodeResolvingResult, LockKind.Write);

                var stream = new DataStream(dataStreamStructureBuilder, AddressingSystemParameters.Default.BlockSize, _lockingManager, lockId);

                var nodeUpdatingStream = new DataStreamNodeUpdating(stream, nodeResolvingResult.ResolvedNode, _fileSystemNodeStorage);

                return(nodeUpdatingStream);
            }
            catch (InvalidPathException)
            {
                throw new FileNotFoundException("Файл не найден по указанному пути (\"{0}\")".FormatWith(fullPathForFile));
            }
            catch (CannotAcquireLockException)
            {
                throw new FileLockedException(
                          "Не удалось открыть файл \"{0}\" с блокировкой на запись: он уже заблокирован на чтение или запись."
                          .FormatWith(fullPathForFile));
            }
        }
        /// <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;
        }
        /// <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);
            }
        }
示例#12
0
        public DataStreamDefinition(int contentsBlockReference, int streamLengthInBytes)
        {
            MethodArgumentValidator.ThrowIfNegative(contentsBlockReference, "contentsBlockReference");
            MethodArgumentValidator.ThrowIfNegative(streamLengthInBytes, "streamLengthInBytes");

            _contentsBlockIndex  = contentsBlockReference;
            _streamLengthInBytes = streamLengthInBytes;
        }
        public AddressingSystemBlockSizes(int doubleIndirectBlockSize, int lastSingleIndirectBlockSize)
        {
            MethodArgumentValidator.ThrowIfNegative(doubleIndirectBlockSize, "doubleIndirectBlockSize");
            MethodArgumentValidator.ThrowIfNegative(lastSingleIndirectBlockSize, "lastSingleIndirectBlockSize");

            DoubleIndirectBlockSize     = doubleIndirectBlockSize;
            LastSingleIndirectBlockSize = lastSingleIndirectBlockSize;
        }
        /// <summary>
        /// Удаляет пустую папку, расположенную по указанному пути. Непустые папки в этой версии удалить вызовом одного метода
        /// нельзя.
        /// </summary>
        /// <param name="folderPath">Путь, указывающий, какую папку надо удалить.</param>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="FolderNotEmptyException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public void DeleteFolder(string folderPath)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(folderPath, "folderPath");

            if (_pathBuilder.PointsToRoot(folderPath))
            {
                throw new InvalidPathException("Не получилось удалить папку: нельзя удалить корень файловой системы.");
            }

            try
            {
                string folderName;

                var parentFolderResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(folderPath, out folderName);

                FolderNode folderToRemoveDirectoryFrom = parentFolderResolvingResult.ResolvedNode;

                var allFolders = _nodeResolver.GetAllFoldersFrom(folderToRemoveDirectoryFrom);

                FolderNode folderToRemove =
                    allFolders.FirstOrDefault(folderNode => _namesComparer.Equals(folderNode.Name, folderName));

                if (folderToRemove == null)
                {
                    throw new FolderNotFoundException("Не найдена папка для удаления (\"0\")".FormatWith(folderPath));
                }

                if ((folderToRemove.FileReferencesStreamDefinition.StreamLengthInBytes > 0) || (folderToRemove.FolderReferencesStreamDefinition.StreamLengthInBytes > 0))
                {
                    throw new FolderNotEmptyException("Не удалось удалить папку: она не пуста"); // Note: блокировки не проверяю. В пустой папке блокировать нечего.
                }

                var idsOfFolderUnderGivenOne = _nodeResolver.GetIdsOfAllFoldersUnderGivenOne(folderPath);

                // TODO: посмотреть на исключения этого метода.
                _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveDirectoryFrom, folderToRemove.DiskBlockIndex, folderToRemoveDirectoryFrom.FolderReferencesStreamDefinition);

                _freeBlockManager.MarkBlocksAsFree(new[]
                {
                    folderToRemove.FileReferencesStreamDefinition.ContentsBlockIndex,
                    folderToRemove.FolderReferencesStreamDefinition.ContentsBlockIndex,
                    folderToRemove.DiskBlockIndex
                });

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(parentFolderResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(parentFolderResolvingResult.ResolvedNode.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(folderToRemove.Id);
                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(idsOfFolderUnderGivenOne);
            }
            catch (CannotResolvePathException)
            {
                throw new FolderNotFoundException("Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(folderPath));
            }
            catch (InvalidPathException)
            {
                throw new FolderNotFoundException("Не удалось найти папку по указанному пути (\"{0}\")".FormatWith(folderPath));
            }
        }
示例#15
0
        /// <summary>
        /// Устанавливает в качестве текущего блок заданного номера.
        /// </summary>
        /// <param name="newPosition"></param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public void SetPosition(int newPosition)
        {
            if (newPosition == EnumeratorAddressable <IDiskBlock> .IndexOfPositionBeforeFirstElement)
            {
                this.Reset();
                return;
            }

            MethodArgumentValidator.ThrowIfNegative(newPosition, "newPosition");

            if (newPosition >= _numberOfBlocks)
            {
                throw new ArgumentOutOfRangeException("newPosition", "Невозможно установить позицию за границей массива");
            }

            #region совсем топорная версия
//            if (newPosition < _position)
//            {
//                this.Reset();
//            }
//
//            while (_position != newPosition)
//            {
//                this.MoveNext();
//            }
//
            //return;
            #endregion

            var compositeIndex = new CompositeIndex(newPosition,
                                                    new[]
            {
                _addressingSystemParameters.IndirectBlockReferencesCountInDoubleIndirectBlock,
                _addressingSystemParameters.DataBlockReferencesCountInSingleIndirectBlock
            });

            var sizes = _blockSizesCalculator.GetSizesOfAddressingBlocksSufficientToStoreItems(newPosition);

            _doubleIndirectListEnumerator.SetPosition(compositeIndex.CompositeValue[0]);

            bool isLastDoubleIndirectionBlock = _doubleIndirectListEnumerator.IsAtLastElement;

            int numberOfSingleIndirectBlockReferences =
                isLastDoubleIndirectionBlock ?
                _addressingSystemSizesOfLastBlocks.LastSingleIndirectBlockSize
                : _addressingSystemParameters.DataBlockReferencesCountInSingleIndirectBlock;

            this.InitializeSingleIndirectionBlock(
                _doubleIndirectListEnumerator.Current,
                numberOfSingleIndirectBlockReferences,
                compositeIndex.CompositeValue[1]);

            this.InitializeCurrentBlockBrowser();

            _position = newPosition;
        }
示例#16
0
        /// <summary>
        ///
        /// </summary>
        /// <exception cref="LockNotFoundException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        public void ReleaseLock(Guid associatedLockId)
        {
            MethodArgumentValidator.ThrowIfIsDefault <Guid>(associatedLockId, "associatedLockId");
            bool removedSuccessfully = _idsOfAssociatedFileLocks.Remove(associatedLockId);

            if (!removedSuccessfully)
            {
                throw new LockNotFoundException("Блокировка с идентификатором {0} не найдена.".FormatWith(associatedLockId));
            }
        }
示例#17
0
        /// <summary>
        /// Возвращает сведения о всех подпапках в указанной директории (<paramref name="folderToGetSubfoldersOf"/>). Работает без рекурсии.
        /// </summary>
        /// <param name="folderToGetSubfoldersOf">Папка, поддиректории которой надо вернуть.</param>
        /// <returns>Сведения о всех папках в указанной директории (<paramref name="folderToGetSubfoldersOf"/>)</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public ReadOnlyCollection <FolderInfo> GetAllFoldersFrom(string folderToGetSubfoldersOf)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(folderToGetSubfoldersOf, "folderToGetSubfoldersOf");

            lock (_operationExecutionCriticalSection)
            {
                ThrowIfDisposed();
                return(_nodeResolver.GetAllFoldersFrom(folderToGetSubfoldersOf));
            }
        }
        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 FileNode(string name, Guid id, int diskBlockIndex, DataStreamDefinition fileContentsStreamDefinition, DateTime lastModificationTimeUtc, DateTime creationTimeUtc, Guid version)
            : base(name, id, diskBlockIndex, version, creationTimeUtc)
        {
            if (fileContentsStreamDefinition == null)
            {
                throw new ArgumentNullException("fileContentsStreamDefinition");
            }
            MethodArgumentValidator.ThrowIfIsDefault <DateTime>(lastModificationTimeUtc, "lastModificationTimeUtc");
            MethodArgumentValidator.ThrowIfDateIsNonUtc(lastModificationTimeUtc, "lastModificationTimeUtc");

            _fileContentsStreamDefinition = fileContentsStreamDefinition;
            _lastModificationTimeUtc      = lastModificationTimeUtc;
        }
        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);
        }
示例#21
0
        /// <summary>
        /// Переименовывает указанный файл.
        /// </summary>
        /// <param name="fullPathForFile">Путь, указывающий файл для переименования.</param>
        /// <param name="newFileName">Новое имя файла (без пути).</param>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="InvalidNameException"></exception>
        /// <exception cref="FileLockedException"></exception>
        public void RenameFile(string fullPathForFile, string newFileName)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFile, "fullPathForFile");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(newFileName, "newFileName");

            if (_pathBuilder.PointsToRoot(fullPathForFile))
            {
                throw new InvalidPathException("Файл не был переименован: имя файла, который следует переименовать, не может указывать на корень файловой системы");
            }

            _nameValidator.Validate(newFileName);

            try
            {
                string fileName;

                var parentFolderResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(fullPathForFile, out fileName);

                string lastPartOfFullPath = _pathBuilder.GetFileOrFolderName(fullPathForFile);

                if (_namesComparer.Equals(newFileName, lastPartOfFullPath))
                {
                    return;
                }

                ReadOnlyCollection <FileNode> files;
                FileNode fileNode = this.ResolveFileNodeThrowingUserFriendlyErrors(fullPathForFile, parentFolderResolvingResult, fileName, "переименовать", out files);

                if (files.Any(node => _namesComparer.Equals(newFileName, node.Name)))
                {
                    throw new FileAlreadyExistsException("Не удалось переименовать файл: файл с именем \"{0}\" уже существует в папке, где вы производите переименование".FormatWith(newFileName));
                }

                fileNode.Name = newFileName;

                _fileSystemNodeStorage.WriteNode(fileNode);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(parentFolderResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(parentFolderResolvingResult.ResolvedNode.Id);
            }
            catch (CannotResolvePathException)
            {
                throw new FileNotFoundException("Не удалось найти файл {0}".FormatWith(fullPathForFile));
            }
            catch (InvalidPathException)
            {
                throw new FileNotFoundException("Не удалось найти файл {0}".FormatWith(fullPathForFile));
            }
        }
示例#22
0
        internal VirtualFileSystemInfo(Version version, int blockSizeInBytes, int firstNonReservedDiskBlockIndex, int freeSpaceBitmapStartingBlock)
        {
            if (version == null)
            {
                throw new ArgumentNullException("version");
            }
            MethodArgumentValidator.ThrowIfNegative(blockSizeInBytes, "blockSizeInBytes");
            MethodArgumentValidator.ThrowIfNegative(firstNonReservedDiskBlockIndex, "firstNonReservedDiskBlockIndex");
            MethodArgumentValidator.ThrowIfNegative(freeSpaceBitmapStartingBlock, "freeSpaceBitmapStartingBlock");

            Version          = version;
            BlockSizeInBytes = blockSizeInBytes;
            FirstNonReservedDiskBlockIndex = firstNonReservedDiskBlockIndex;
            FreeSpaceBitmapStartingBlock   = freeSpaceBitmapStartingBlock;
        }
示例#23
0
        /// <summary>
        /// Копирует указанный файл.
        /// </summary>
        /// <param name="fullPathForFileToBeCopied">Полный путь (от корня), указывающий файл, который следует скопировать.</param>
        /// <param name="newPathThatWillPointToTheCopyOfFile">Полный путь (от корня), указывающий, где будет находиться и как называться копия файла.</param>
        /// <param name="taskToken"></param>
        /// <returns>Описание копии файла.</returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="FileLockedException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="MaximumFileCountReachedException"></exception>
        /// <exception cref="TaskCancelledException"></exception>
        internal FileInfo CopyFile(string fullPathForFileToBeCopied, string newPathThatWillPointToTheCopyOfFile, IFileSystemCancellableTaskToken taskToken)
        {
            if (taskToken == null)
            {
                throw new ArgumentNullException("taskToken");
            }
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathForFileToBeCopied, "fullPathForFileToBeCopied");
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(newPathThatWillPointToTheCopyOfFile, "newPathThatWillPointToTheCopyOfFile");

            if (_namesComparer.Equals(fullPathForFileToBeCopied, newPathThatWillPointToTheCopyOfFile))
            {
                return
                    (new FileInfo(_nodeResolver.ResolveFileNodeByPath(newPathThatWillPointToTheCopyOfFile).ResolvedNode, newPathThatWillPointToTheCopyOfFile));
            }

            lock (_operationExecutionCriticalSection)
            {
                ThrowIfDisposed(); // так себе проверка на этот раз.
            }

            // Note: не смотрю, хватит ли там места. Хотя отрицательный ответ на такой вопрос мог бы стать поводом, чтобы ничего не копировать.
            try
            {
                CopyFileContents(taskToken, fullPathForFileToBeCopied, newPathThatWillPointToTheCopyOfFile);

                return
                    (new FileInfo(_nodeResolver.ResolveFileNodeByPath(newPathThatWillPointToTheCopyOfFile).ResolvedNode, newPathThatWillPointToTheCopyOfFile));
            }
            catch (Exception)
            {
                try
                {
                    this.DeleteFile(newPathThatWillPointToTheCopyOfFile);
                }
                catch (InvalidPathException)
                {
                }
                catch (ObjectDisposedException)
                {
                    throw new ObjectDisposedException("Работа с файловой системой была вами завершена принудительным вызовом метода Dispose() - до того, как был докопирован файл. Рекомендуется удалить следующий файл при очередном запуске системы (простите - в текущей версии ничего более удобного не сделано): \"{0}\"".FormatWith(newPathThatWillPointToTheCopyOfFile));
                }
                catch (FileNotFoundException)
                {
                }

                throw;
            }
        }
        /// <summary>
        /// Делает из абсолютного пути к папке <paramref name="fullPathToTurnIntoRelative"/>, ее путь относительно папки <paramref name="fullPathForFolderToGetRelativePathAgainst"/>.
        /// </summary>
        /// <param name="fullPathForFolderToGetRelativePathAgainst"></param>
        /// <param name="fullPathToTurnIntoRelative"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        internal string GetRelativePath(string fullPathForFolderToGetRelativePathAgainst, string fullPathToTurnIntoRelative)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty("fullPathForFolderToGetRelativePathAgainst", fullPathForFolderToGetRelativePathAgainst);
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty("fullPathToTurnIntoRelative", fullPathToTurnIntoRelative);

            // Note: ordinal ignore case - выносить надо отсюда. Такие вещи надо настраивать в каком-то одном месте.
            if (!fullPathToTurnIntoRelative.StartsWith(fullPathForFolderToGetRelativePathAgainst, StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException("Чтобы получить путь одной папки относительно другой, необходимо, чтобы та папка, относительно которой считается путь, была родительской папкой (прямо или косвенно) для той, которой считается путь.");
            }

            return
                (fullPathToTurnIntoRelative
                 .Substring(fullPathForFolderToGetRelativePathAgainst.Length, fullPathToTurnIntoRelative.Length - fullPathForFolderToGetRelativePathAgainst.Length)
                 .TrimStart(new[] { _directorySeparator }));
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        internal string GetFileOrFolderName(string path)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(path, "fullPath");

            if (_nameComparer.Equals(_rootPath, path))
            {
                return(path);
            }

            if (path.IndexOf(_directorySeparator) < 0)
            {
                return(path);
            }

            return(path.Remove(0, path.LastIndexOf(_directorySeparator) + 1));
        }
示例#26
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="name"></param>
        /// <param name="id"></param>
        /// <param name="diskBlockIndex"></param>
        /// <param name="version"></param>
        /// <param name="creationTimeUtc"></param>
        /// <exception cref="InvalidNameException"></exception>
        protected Node(string name, Guid id, int diskBlockIndex, Guid version, DateTime creationTimeUtc)
        {
            MethodArgumentValidator.ThrowIfIsDefault <Guid>(version, "version");
            MethodArgumentValidator.ThrowIfIsDefault <Guid>(id, "id");
            MethodArgumentValidator.ThrowIfIsDefault <DateTime>(creationTimeUtc, "creationTimeUtc");
            MethodArgumentValidator.ThrowIfDateIsNonUtc(creationTimeUtc, "creationTimeUtc");

            this.InitializeValidator();

            _nameValidator.Validate(name);

            _creationTimeUtc = creationTimeUtc;
            _diskBlockIndex  = diskBlockIndex;
            _id      = id;
            _version = version;
            _name    = name;
        }
示例#27
0
        /// <summary>
        /// Создает новый файл по указанному пути.
        /// Примечание: в текущей версии не создает недостающие папки.
        /// </summary>
        /// <param name="fullPathToFile">Полный путь (включая имя файла), указывающий, где будет находиться новый файл.</param>
        /// <returns>Сведения о только что созданном файле.</returns>
        /// <exception cref="InvalidPathException">Если указанный путь невалиден.</exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="FolderNotFoundException">Если путь (<paramref name="fullPathToFile"/>), за исключением последней части (имени нового файла), указывает на несуществующую папку.</exception>
        /// <exception cref="FileAlreadyExistsException"></exception>
        /// <exception cref="InsufficientSpaceException"></exception>
        /// <exception cref="MaximumFileCountReachedException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public FileInfo CreateFile(string fullPathToFile)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(fullPathToFile, "fullPathToFile");

            if (_pathBuilder.PointsToRoot(fullPathToFile))
            {
                throw new InvalidPathException("Не удалось создать файл: в качестве пути к файлу нельзя указать корень файловой системы");
            }

            _pathValidator.Validate(fullPathToFile);

            try
            {
                string fileName;

                var nodeResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(fullPathToFile, out fileName);

                FolderNode parentFolder = nodeResolvingResult.ResolvedNode;

                var newFileInfo = new FileInfo(this.CreateFile(parentFolder, fileName), fullPathToFile);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(nodeResolvingResult.FoldersPassedWhileResolving);

                return(newFileInfo);
            }
            catch (InsufficientSpaceException)
            {
                throw new InsufficientSpaceException("Недостаточно свободного места на диске для создания файла.");
            }
            catch (MaximumFileSizeReachedException)
            {
                throw new MaximumFileCountReachedException("Не удалось добавить файл: папка, в которую вы добавляете файл, не может вместить их больше, чем уже вмещает.");
            }
            catch (NoFreeBlocksException)
            {
                throw new InsufficientSpaceException("Недостаточно свободного места на диске для создания файла.");
            }
            catch (InvalidPathException)
            {
                throw new FolderNotFoundException("Не получилось создать файл по указанному пути (\"{0}\"). Не найдена папка, в которой следует создать файл. (В текущей версии недостающие папки не создаются автоматически)".FormatWith(fullPathToFile));
            }
            catch (CannotResolvePathException)
            {
                throw new FolderNotFoundException("Не получилось создать файл по указанному пути (\"{0}\"). Не найдена папка, в которой следует создать файл. (В текущей версии недостающие папки не создаются автоматически)".FormatWith(fullPathToFile));
            }
        }
        public NodeResolver(
            IVirtualDisk virtualDisk,
            FileSystemNodeStorage fileSystemNodeStorage,
            IEqualityComparer <string> namesComparer,
            int rootBlockIndex,
            string rootFolderPath,
            char directorySeparatorChar,
            IPathValidator pathValidator,
            PathBuilder pathBuilder)
        {
            if (virtualDisk == null)
            {
                throw new ArgumentNullException("virtualDisk");
            }
            if (fileSystemNodeStorage == null)
            {
                throw new ArgumentNullException("fileSystemNodeStorage");
            }
            if (namesComparer == null)
            {
                throw new ArgumentNullException("namesComparer");
            }
            if (pathBuilder == null)
            {
                throw new ArgumentNullException("pathBuilder");
            }
            if (String.IsNullOrEmpty(rootFolderPath))
            {
                throw new ArgumentNullException("rootFolderPath");
            }
            MethodArgumentValidator.ThrowIfNegative(rootBlockIndex, "rootBlockIndex");

            if (rootBlockIndex >= virtualDisk.NumberOfBlocks)
            {
                throw new ArgumentOutOfRangeException("rootBlockIndex");
            }

            _virtualDisk            = virtualDisk;
            _pathBuilder            = pathBuilder;
            _fileSystemNodeStorage  = fileSystemNodeStorage;
            _namesComparer          = namesComparer;
            _rootBlockIndex         = rootBlockIndex;
            _rootFolderPath         = rootFolderPath;
            _directorySeparatorChar = directorySeparatorChar;
            _pathValidator          = pathValidator;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        /// <exception cref="FolderNotFoundException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        public ReadOnlyCollection <FileInfo> GetAllFilesFrom(string path)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(path, "path");

            try
            {
                var nodeResolvingResult = this.ResolveFolderNodeByPath(path);

                FolderNode parentFolder = nodeResolvingResult.ResolvedNode;

                return(this.GetAllFilesFrom(parentFolder).Select(file => new FileInfo(file, _pathBuilder.CombinePaths(path, file.Name))).ToList().AsReadOnly());
            }
            catch (InvalidPathException exception)
            {
                throw new FolderNotFoundException("Не удалось получить файлы, содержащиеся в папке \"{0}\". {1}".FormatWith(path, exception.Message));
            }
        }
示例#30
0
        /// <summary>
        /// Удаляет указанный файл.
        /// </summary>
        /// <param name="filePath">Путь, указывающий удаляемый файл.</param>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="FileLockedException"></exception>
        /// <exception cref="InvalidPathException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ObjectDisposedException"></exception>
        public void DeleteFile(string filePath)
        {
            MethodArgumentValidator.ThrowIfStringIsNullOrEmpty(filePath, "filePath");

            if (_pathBuilder.PointsToRoot(filePath))
            {
                throw new InvalidPathException("Не получилось удалить файл: нельзя удалить корень файловой системы.");
            }

            try
            {
                string fileName;

                var parentFolderResolvingResult = _nodeResolver.ResolveParentFolderNodeByPath(filePath, out fileName);

                ReadOnlyCollection <FileNode> files;
                FolderNode folderToRemoveFileFrom = parentFolderResolvingResult.ResolvedNode;
                FileNode   fileToRemove           = ResolveFileNodeThrowingUserFriendlyErrors(filePath, parentFolderResolvingResult, fileName, "удалить", out files);

                // очистка всех данных.
                using (var dataStream = this.OpenFileForWriting(filePath))
                {
                    dataStream.Truncate();
                }

                // TODO: поглядеть на исключения этого метода.
                _blockReferenceListsEditor.TakeOutABlockFromBlockReferenceList(folderToRemoveFileFrom, fileToRemove.DiskBlockIndex, folderToRemoveFileFrom.FileReferencesStreamDefinition);

                _freeBlockManager.MarkBlockAsFree(fileToRemove.DiskBlockIndex);
                _freeBlockManager.MarkBlockAsFree(fileToRemove.FileContentsStreamDefinition.ContentsBlockIndex);

                _folderEnumeratorRegistry.InvalidateEnumeratorsFor(parentFolderResolvingResult.FoldersPassedWhileResolving);
                _folderEnumeratorRegistry.InvalidateEnumeratorsForFolder(parentFolderResolvingResult.ResolvedNode.Id);
            }
            catch (CannotResolvePathException)
            {
                throw new FileNotFoundException("Не удалось найти файл {0}".FormatWith(filePath));
            }
            catch (InvalidPathException)
            {
                throw new FileNotFoundException("Не удалось найти файл {0}".FormatWith(filePath));
            }
        }