Example #1
0
        internal PartitionStream ReadStream(IBlobFileMetadata fileMetadata)
        {
            if (fileMetadata == null)
            {
                throw new ArgumentNullException("fileMetadata");
            }

            if (fileMetadata.BlobStartPosition >= fileMetadata.BlobEndPosition)
            {
                throw new Exception(string.Format("Индекс начала файла не может быть равным или больше индекса окончания файла"));
            }

            //поток закрывает объект, предоставляющий средства потоковой передачи
            IBlobFileHeader fileHeader           = (IBlobFileHeader)this.GetFileHeader(fileMetadata.BlobStartPosition);
            long            contentStartPosition = fileMetadata.BlobStartPosition + BlobStreamAdapter.SystemHeaderLength + fileHeader.HeaderLength;
            PartitionStream stream = new PartitionStream(this.BlobStream, contentStartPosition, fileMetadata.Size);

            return(stream);
        }
        public void Restore()
        {
            //проверяем поочередно каждый блоб каждого контейнера
            foreach (IBlobContainerMetadata containerMetadata in this.Containers)
            {
                try
                {
                    //получаем все блобы контейнера
                    ICollection <IBlobMetadata> blobs = this.DataAdapter.BlobMetadataAdapter.GetBlobs(containerMetadata.ID);
                    if (blobs == null || blobs.Count == 0)
                    {
                        continue;
                    }

                    BlobContainer container = new BlobContainer(this.DataAdapter, containerMetadata);
                    //Алгоритм восстановления метаданных
                    //1 - получаем все блобы всех контейнеров
                    //нужно посмотреть все блобы и закрытие и открытые.
                    //потому что после запуска процедуры восстановления метаданных может пойти запись в не до конца восстановленный блоб
                    //и он станет закрытым, но восстановление не завершилось.

                    /*foreach (IBlobMetadata blobMetadata in blobs)
                     * {
                     *  object tmp = blobMetadata.Closed;
                     * }*/

                    //2 - для каждого блоба смотрим его позицию, до которой мы проверили целостность этого блоба
                    foreach (IBlobMetadata blobMetadata in blobs)
                    {
                        Blob blob = new Blob(container, blobMetadata);
                        try
                        {
                            long blobIntegrityPosition = blobMetadata.IntegrityPosition;
                            long filelenth             = blob.File.Length;

                            //целостность метаданных файлов блоба до конца проверена
                            while (blobIntegrityPosition < filelenth)
                            {
                                using (FileStream fs = blob.File.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                                {
                                    BlobStreamAdapter streamAdapter = new BlobStreamAdapter(fs);
                                    if (blobIntegrityPosition == 0)
                                    {
                                        //блоб может начинаться с системного заголовка.
                                        //а может с файла
                                        //тогда нужно сместить начальную позицию на этот системный заголовок
                                        //читаем позицию первого файла
                                        long firstFilePosition = streamAdapter.GetFirstFilePosition();
                                        blob.UpdateIntegrityPosition(firstFilePosition);
                                        blobIntegrityPosition = blobMetadata.IntegrityPosition;
                                    }


                                    //заголовок из файла
                                    object          fileHeaderObj  = streamAdapter.GetFileHeader(blobIntegrityPosition);
                                    IFileHeader     fileHeader     = (IFileHeader)fileHeaderObj;
                                    IBlobFileHeader blobFileHeader = (IBlobFileHeader)fileHeaderObj;

                                    long fileStartPosition = blobMetadata.IntegrityPosition;
                                    if (fileStartPosition != blobFileHeader.ContentAbsoluteStartPosition)
                                    {
                                        throw new Exception(string.Format("Позиция целостности блоба не соответствует позиции начала файла"));
                                    }

                                    long fileEndPosition = fileStartPosition
                                                           + BlobStreamAdapter.SystemHeaderLength
                                                           + blobFileHeader.HeaderLength
                                                           + blobFileHeader.ContentLength;

                                    //восстанавливаем метаданные, если их нет
                                    this.EnsureMetadata(blobMetadata, fileHeader, fileStartPosition, fileEndPosition);

                                    //увеличиваем позицию целостности метаданных блоба
                                    blob.UpdateIntegrityPosition(fileEndPosition);
                                    blobIntegrityPosition = blobMetadata.IntegrityPosition;
                                }
                            }
                        }
                        catch (Exception blobEx)
                        {
                            this.DataAdapter.Logger.WriteFormatMessage("Ошибка при восстановлении метаданных блоба с идентификатором {0} для контейнера {1}. Текст ошибки: {2}",
                                                                       blob.ID,
                                                                       containerMetadata.Path,
                                                                       blobEx);
                        }
                    }
                }
                catch (Exception containerEx)
                {
                    this.DataAdapter.Logger.WriteFormatMessage("Ошибка при восстановлении метаданных контейнера {0}. Текст ошибки: {1}",
                                                               containerMetadata.Path,
                                                               containerEx);
                }
            }
        }
Example #3
0
        private byte[] ReadContent(Guid fileUniqueID, Guid fileVersionUniqueID, long blobStartPosition, long blobEndPosition)
        {
            if (fileUniqueID == Guid.Empty)
            {
                throw new ArgumentNullException("fileUniqueID");
            }

            if (fileVersionUniqueID == Guid.Empty)
            {
                throw new ArgumentNullException("fileVersionUniqueID");
            }

            if (blobStartPosition < 0)
            {
                throw new ArgumentNullException("blobStartPosition");
            }

            if (blobEndPosition < 1)
            {
                throw new ArgumentNullException("blobEndPosition");
            }

            if (blobStartPosition >= blobEndPosition)
            {
                throw new Exception(string.Format("Индекс начала файла не может быть равным или больше индекса окончания файла"));
            }

            long length = blobEndPosition - blobStartPosition;

            if (blobEndPosition > this.BlobStream.Length)
            {
                throw new IndexOutOfRangeException("Индекс окончания файла превысил размер блоба");
            }

            //сырые данные файла (со всеми заголовками и хешами)
            byte[] rawData = new byte[length];
            if (length > Int32.MaxValue)
            {
                throw new Exception(string.Format("Файлы размером более 2GB в данный момент не поддерживаются"));
            }
            else
            {
                this.BlobStream.Seek(blobStartPosition, SeekOrigin.Begin);
                this.BlobStream.Read(rawData, 0, rawData.Length);
            }

            //1 - проверка системного префикса.
            //системный заголовок занимает первые _systemHeaderLength байт
            for (int i = 0; i < SystemHeaderFixedBytes.Length; i++)
            {
                if (SystemHeaderFixedBytes[i] != rawData[i])
                {
                    throw new Exception(string.Format("Битый заголовок файла (позиция {0}). Не удалось прочитать системный заголовок файла.",
                                                      i));
                }
            }

            //проверка заголовка.
            object          header     = this.GetFileHeader(rawData);
            IBlobFileHeader blobHeader = (IBlobFileHeader)header;

            long contentLength = blobHeader.ContentLength;

            if (contentLength == 0)
            {
                throw new Exception(string.Format("Не удалось считать размер содержимого файла"));
            }

            byte[] content = new byte[contentLength];
            Array.Copy(rawData, BlobStreamAdapter.SystemHeaderLength + blobHeader.HeaderLength, content, 0, contentLength);

            //проверка идентификаторов версий
            IFileHeader fileHeader = (IFileHeader)header;

            if (fileUniqueID != fileHeader.UniqueID)
            {
                throw new Exception(string.Format("Идентификатор файла в метаданных не совпадает с идентификатором файла в блобе"));
            }

            if (fileVersionUniqueID != fileHeader.VersionUniqueID)
            {
                throw new Exception(string.Format("Идентификатор версии файла в метаданных не совпадает с идентификатором версии файла в блобе"));
            }

            byte[] originalHeaderHash = new byte[16];//хеш заголовка файла из самого блоба
            Array.Copy(rawData, SystemHeaderFixedBytes.Length + BlobConsts.BlobFile.HeaderSizeBytesLength, originalHeaderHash, 0, originalHeaderHash.Length);
            //хеш вычисленный по байтам заголовка
            byte[] currentHeaderHash = this.HashAlgorithm.ComputeHash(rawData, BlobStreamAdapter.SystemHeaderLength, blobHeader.HeaderLength);
            bool   headerHashInvalid = !originalHeaderHash.SequenceEqual(currentHeaderHash);

            if (headerHashInvalid)
            {
                throw new Exception(string.Format("Битый заголовок файла. Не удалось прочитать системный заголовок файла."));
            }

            //3 - проверка хеша содержимого.
            byte[] originalContentHash = new byte[16];//хеш содержимого файла из самого блоба
            Array.Copy(rawData, SystemHeaderFixedBytes.Length + BlobConsts.BlobFile.HeaderSizeBytesLength + originalHeaderHash.Length, originalContentHash, 0, originalContentHash.Length);
            byte[] currentContentHash = this.HashAlgorithm.ComputeHash(content);
            bool   contentHashInvalid = !originalContentHash.SequenceEqual(currentContentHash);

            if (contentHashInvalid)
            {
                throw new Exception(string.Format("Битое содержимое файла. Не удалось прочитать содержимое файла."));
            }

            rawData             = null;
            originalHeaderHash  = null;
            currentHeaderHash   = null;
            originalContentHash = null;
            currentContentHash  = null;

            return(content);
        }
Example #4
0
        /// <summary>
        /// Создает метаданные существующего файла.
        /// </summary>
        /// <param name="storageMetadata">Метаданные хранилища.</param>
        /// <param name="blobMetadata">Метаданные блоба.</param>
        /// <param name="folderMetadata">Метаданные папки.</param>
        /// <param name="fileHeader">Заголовок файла.</param>
        /// <param name="blobStartPosition">Начальная позиция файла в блобе.</param>
        /// <param name="blobEndPosition">Конечная позиция файла в блобе.</param>
        /// <returns></returns>
        public IBlobFileMetadata AddExistsFileVersion(IStorageMetadata storageMetadata, IBlobMetadata blobMetadata, IFolderMetadata folderMetadata, IFileHeader fileHeader, long blobStartPosition, long blobEndPosition)
        {
            if (storageMetadata == null)
            {
                throw new ArgumentNullException("storageMetadata");
            }

            if (blobMetadata == null)
            {
                throw new ArgumentNullException("blobMetadata");
            }

            if (folderMetadata == null)
            {
                throw new ArgumentNullException("folderMetadata");
            }

            if (fileHeader == null)
            {
                throw new ArgumentNullException("fileHeader");
            }

            if (blobStartPosition < 0)
            {
                throw new ArgumentNullException("blobStartPosition");
            }

            IBlobFileHeader blobHeader  = (IBlobFileHeader)((object)fileHeader);
            FileMetadata    file        = this.FileAdapter.GetFile(fileHeader.UniqueID, folderMetadata);
            bool            justCreated = false;

            if (file == null)
            {
                justCreated          = true;
                file                 = new FileMetadata(this.FileAdapter);
                file.UniqueID        = fileHeader.UniqueID;
                file.VersionUniqueID = fileHeader.VersionUniqueID;
                file.FolderID        = folderMetadata.ID;
                file.FolderMetadata  = folderMetadata;
                file.Name            = fileHeader.FileName;

                file.BlobID            = blobMetadata.ID;
                file.BlobStartPosition = blobStartPosition;
                file.BlobEndPosition   = blobEndPosition;
                file.Deleted           = false;
                file.Size         = blobHeader.ContentLength;
                file.TimeCreated  = fileHeader.TimeCreated;
                file.TimeModified = fileHeader.TimeCreated;

                this.FileAdapter.UpdateFileTransparent(file);
            }
            else
            {
                if (file.Versions.Any(x => x.UniqueID == fileHeader.VersionUniqueID))
                {
                    throw new Exception(String.Format("Версия с идентификатором [{0}] уже существует.", fileHeader.VersionUniqueID.ToString()));
                }
            }

            //создание версии файла
            FileVersionMetadata version = new FileVersionMetadata(file);

            version.UniqueID          = fileHeader.VersionUniqueID;
            version.BlobID            = blobMetadata.ID;
            version.BlobStartPosition = blobStartPosition;
            version.BlobEndPosition   = blobEndPosition;
            version.Size             = blobHeader.ContentLength;
            version.TimeCreated      = fileHeader.TimeCreated;
            version.CreatedStorageID = storageMetadata.ID;
            version.Name             = fileHeader.FileName;

            //сохранение версии
            this.FileAdapter.VersionAdapter.InsertVerion(file, version);
            file.ResetVersions();

            //обновление параметров существующего файла
            if (!justCreated)
            {
                bool fileUpdate = false;
                if (version.TimeCreated > file.TimeModified)
                {
                    file.TimeModified    = version.TimeCreated;
                    file.VersionUniqueID = version.UniqueID;
                    file.BlobID          = version.BlobID;
                    fileUpdate           = true;
                }

                if (version.TimeCreated < file.TimeCreated)
                {
                    file.TimeCreated = version.TimeCreated;
                    fileUpdate       = true;
                }

                //обновление файла
                if (fileUpdate)
                {
                    this.FileAdapter.UpdateFileTransparent(file);
                }
            }

            return(file);
        }