Esempio n. 1
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="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);
            }
        }
        /// <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);
        }