/// <summary> /// Записывает содержимое файла в блоб. /// </summary> /// <param name="fileMetadata">Матаданные файла.</param> /// <param name="stream">Содержимое файла.</param> /// <param name="remoteTimeCreated">Время создания версии с удаленного узла.</param> /// <returns></returns> internal BlobFileInfo Write(IBlobFileMetadata fileMetadata, Stream stream, DateTime?remoteTimeCreated = null) { if (fileMetadata == null) { throw new ArgumentNullException("fileMetadata"); } if (stream == null) { throw new ArgumentNullException("stream"); } this.Container.DataAdapter.Logger.WriteFormatMessage("Blob.Write:Начало записи содержимого в блоб, file.UniqueID: {0}", fileMetadata.UniqueID); BlobFileInfo blobFileInfo = new BlobFileInfo(); blobFileInfo.BlobID = this.ID; bool closeBlob = false; DateTime timeCreated; if (remoteTimeCreated.HasValue) { timeCreated = remoteTimeCreated.Value; } else { //начиная с 4ой версии хранится время в UTC timeCreated = DateTime.Now.ToUniversalTime(); } using (FileStream fs = this.File.Open(FileMode.Append, FileAccess.Write, FileShare.Read)) { BlobStreamAdapter streamAdapter = new BlobStreamAdapter(fs); blobFileInfo.BlobStartPosition = fs.Length; streamAdapter.Write(fileMetadata, stream, timeCreated); blobFileInfo.BlobEndPosition = fs.Length; blobFileInfo.TimeCreated = timeCreated; closeBlob = fs.Length > this.Container.DataAdapter.MaxBlobSize; } if (closeBlob) { this.Metadata.Closed = true; this.Container.DataAdapter.BlobMetadataAdapter.SaveBlob(this.Metadata); } this.Container.DataAdapter.Logger.WriteFormatMessage("Blob.Write:Окончание записи содержимого в блоб, file.UniqueID: {0}. Блоб был закрыт после записи файла: {1}", fileMetadata.UniqueID, closeBlob); return(blobFileInfo); }
/// <summary> /// Считывает поток данных файла из блоба. /// </summary> /// <param name="fileMetadata">Метаданные файла.</param> /// <returns></returns> internal Stream ReadStream(IBlobFileMetadata fileMetadata) { if (fileMetadata == null) { throw new ArgumentNullException("fileMetadata"); } //поток закрывает объект, предоставляющий средства потоковой передачи FileStream fs = this.File.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); BlobStreamAdapter streamAdapter = new BlobStreamAdapter(fs); PartitionStream stream = streamAdapter.ReadStream(fileMetadata); return(stream); }
/// <summary> /// Возвращает содержимое файла. /// </summary> /// <param name="fileMetadata">Метаданные файла.</param> /// <returns></returns> internal byte[] Read(IBlobFileMetadata fileMetadata) { if (fileMetadata == null) { throw new ArgumentNullException("fileMetadata"); } if (fileMetadata.BlobStartPosition < 0) { throw new ArgumentNullException("fileMetadata.BlobStartPosition"); } if (fileMetadata.BlobEndPosition < 1) { throw new ArgumentNullException("fileMetadata.BlobEndPosition"); } this.Container.DataAdapter.Logger.WriteFormatMessage("Blob.Read:Начало чтения содержимого из блоба, blobStartPosition: {0}, blobEndPosition: {1}", fileMetadata.BlobStartPosition, fileMetadata.BlobEndPosition); //для операции чтения блоб должен всегда существовать if (!this.File.Exists) { throw new Exception(string.Format("Не удалось найти блоб по пути {0}", this.File.FullName)); } byte[] content = null; using (FileStream fs = this.File.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { BlobStreamAdapter streamAdapter = new BlobStreamAdapter(fs); content = streamAdapter.Read(fileMetadata); } this.Container.DataAdapter.Logger.WriteFormatMessage("Blob.Read:Окончание чтения содержимого из блоба, blobStartPosition: {0}, blobEndPosition: {1}", fileMetadata.BlobStartPosition, fileMetadata.BlobEndPosition); return(content); }
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); } } }