/// <summary> /// Initializes a new instance of the <cref name="BackupInfo"/> class. /// </summary> /// <param name="directory">Folder path that contains the backup.</param> /// <param name="option"><cref name="BackupOption"/> that was used to take the backup.</param> /// <param name="version"><cref name="BackupVersion"/> of the backup.</param> /// <param name="startBackupVersion"><cref name="BackupVersion"/> of first logical log record in the backup.</param> /// <param name="backupId">Id of the backup.</param> /// <param name="parentBackupId">Id of the corresponding full backup in case of incremental backup, Guid.Empty in case this is full backup.</param> public BackupInfo(string directory, BackupOption option, BackupVersion version, BackupVersion startBackupVersion, Guid backupId, Guid parentBackupId) { this.Directory = directory; this.Option = option; this.Version = version; this.StartBackupVersion = startBackupVersion; this.BackupId = backupId; this.ParentBackupId = parentBackupId; }
/// <summary> /// Initializes a new instance of the <cref name="BackupInfo"/> class. /// </summary> /// <param name="directory">Folder path that contains the backup.</param> /// <param name="option"><cref name="BackupOption"/> that was used to take the backup.</param> /// <param name="version"><cref name="BackupVersion"/> of the backup.</param> public BackupInfo(string directory, BackupOption option, BackupVersion version) { this.Directory = directory; this.Option = option; this.Version = version; this.StartBackupVersion = BackupVersion.InvalidBackupVersion; this.BackupId = Guid.Empty; this.ParentBackupId = Guid.Empty; }
private async Task TestReaderWriterAsync(BackupVersion version, Func <IBackupWriter, Task> write, Func <IBackupReader, Task> read) { using (var stream = new MemoryStream()) { using (var writer = new BackupWriter(serializer, stream, true, version)) { await write(writer); } stream.Position = 0; using (var reader = new BackupReader(serializer, stream)) { await read(reader); } } }
/// <summary> /// Called when we are about to import a book but are not importing the main translation. /// </summary> /// <param name="nCanonicalBookNumber"></param> /// <param name="fMakeBackup">This should be true if we are importing a back /// translation.</param> /// <returns>The version of the book in the imported version if available; otherwise /// the current version of the book (in which case a backup will be made first if /// <c>fMakeBackup</c> is <c>true</c>.</returns> public IScrBook PrepareBookNotImportingVern(int nCanonicalBookNumber, bool fMakeBackup) { var isvBook = SetCurrentBook(nCanonicalBookNumber, false); if (isvBook != null && ImportedBooks.ContainsKey(nCanonicalBookNumber)) { return(isvBook); } var cvBook = m_scr.FindBook(nCanonicalBookNumber); if (cvBook != null && fMakeBackup) { // Replace any existing book with the imported one. var oldBook = BackupVersion.FindBook(nCanonicalBookNumber); if (oldBook != null) { BackupVersion.BooksOS.Remove(oldBook); } BackupVersion.AddBookCopy(cvBook); } return(cvBook); }
public BackupWriter(IJsonSerializer serializer, Stream stream, bool keepOpen = false, BackupVersion version = BackupVersion.V2) { Guard.NotNull(serializer); this.serializer = serializer; converter = version == BackupVersion.V1 ? new Func <StoredEvent, CompatibleStoredEvent>(CompatibleStoredEvent.V1) : new Func <StoredEvent, CompatibleStoredEvent>(CompatibleStoredEvent.V2); archive = new ZipArchive(stream, ZipArchiveMode.Create, keepOpen); }
public async Task Should_write_and_read_events_to_backup(BackupVersion version) { var randomGenerator = new Random(); var randomDomainIds = new List <DomainId>(); for (var i = 0; i < 100; i++) { randomDomainIds.Add(DomainId.NewGuid()); } DomainId RandomDomainId() { return(randomDomainIds[randomGenerator.Next(randomDomainIds.Count)]); } var sourceEvents = new List <(string Stream, Envelope <MyEvent> Event)>(); for (var i = 0; i < 200; i++) { var @event = new MyEvent(); var envelope = Envelope.Create(@event); envelope.Headers.Add("Id", JsonValue.Create(@event.Id)); envelope.Headers.Add("Index", JsonValue.Create(i)); sourceEvents.Add(($"My-{RandomDomainId()}", envelope)); } await TestReaderWriterAsync(version, async writer => { foreach (var(stream, envelope) in sourceEvents) { var eventData = formatter.ToEventData(envelope, Guid.NewGuid(), true); var eventStored = new StoredEvent(stream, "1", 2, eventData); var index = int.Parse(envelope.Headers["Index"].ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture); if (index % 17 == 0) { await WriteGuidAsync(writer, index.ToString(CultureInfo.InvariantCulture), envelope.Payload.Id); } else if (index % 37 == 0) { await WriteJsonGuidAsync(writer, index.ToString(CultureInfo.InvariantCulture), envelope.Payload.Id); } writer.WriteEvent(eventStored); } }, async reader => { var targetEvents = new List <(string Stream, Envelope <IEvent> Event)>(); await foreach (var @event in reader.ReadEventsAsync(streamNameResolver, formatter)) { var index = int.Parse(@event.Event.Headers["Index"].ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture); var id = Guid.Parse(@event.Event.Headers["Id"].ToString()); if (index % 17 == 0) { var guid = await ReadGuidAsync(reader, index.ToString(CultureInfo.InvariantCulture)); Assert.Equal(id, guid); } else if (index % 37 == 0) { var guid = await ReadJsonGuidAsync(reader, index.ToString(CultureInfo.InvariantCulture)); Assert.Equal(id, guid); } targetEvents.Add(@event); } for (var i = 0; i < targetEvents.Count; i++) { var targetEvent = targetEvents[i].Event.To <MyEvent>(); var targetStream = targetEvents[i].Stream; var sourceEvent = sourceEvents[i].Event.To <MyEvent>(); var sourceStream = sourceEvents[i].Stream; Assert.Equal(sourceEvent.Payload.Id, targetEvent.Payload.Id); Assert.Equal(sourceStream, targetStream); } }); }
public async Task Should_write_and_read_events_to_backup(BackupVersion version) { var stream = new MemoryStream(); var random = new Random(); var randomGuids = new List <Guid>(); for (var i = 0; i < 100; i++) { randomGuids.Add(Guid.NewGuid()); } Guid RandomGuid() { return(randomGuids[random.Next(randomGuids.Count)]); } var sourceEvents = new List <(string Stream, Envelope <IEvent> Event)>(); for (var i = 0; i < 200; i++) { var @event = new MyEvent { GuidNamed = NamedId.Of(RandomGuid(), $"name{i}"), GuidRaw = RandomGuid(), Values = new Dictionary <Guid, string> { [RandomGuid()] = "Key" } }; var envelope = Envelope.Create <IEvent>(@event); envelope.Headers.Add(RandomGuid().ToString(), i); envelope.Headers.Add("Id", RandomGuid().ToString()); envelope.Headers.Add("Index", i); sourceEvents.Add(($"My-{RandomGuid()}", envelope)); } using (var writer = new BackupWriter(serializer, stream, true, version)) { foreach (var(_, envelope) in sourceEvents) { var eventData = formatter.ToEventData(envelope, Guid.NewGuid(), true); var eventStored = new StoredEvent("S", "1", 2, eventData); var index = int.Parse(envelope.Headers["Index"].ToString()); if (index % 17 == 0) { await writer.WriteBlobAsync(index.ToString(), innerStream => { innerStream.WriteByte((byte)index); return(TaskHelper.Done); }); } else if (index % 37 == 0) { await writer.WriteJsonAsync(index.ToString(), $"JSON_{index}"); } writer.WriteEvent(eventStored); } } stream.Position = 0; var targetEvents = new List <(string Stream, Envelope <IEvent> Event)>(); using (var reader = new BackupReader(serializer, stream)) { await reader.ReadEventsAsync(streamNameResolver, formatter, async @event => { var index = int.Parse(@event.Event.Headers["Index"].ToString()); if (index % 17 == 0) { await reader.ReadBlobAsync(index.ToString(), innerStream => { var byteRead = innerStream.ReadByte(); Assert.Equal((byte)index, byteRead); return(TaskHelper.Done); }); } else if (index % 37 == 0) { var json = await reader.ReadJsonAttachmentAsync <string>(index.ToString()); Assert.Equal($"JSON_{index}", json); } targetEvents.Add(@event); }); void CompareGuid(Guid source, Guid target) { Assert.Equal(source, reader.OldGuid(target)); Assert.NotEqual(source, target); } for (var i = 0; i < targetEvents.Count; i++) { var target = targetEvents[i].Event.To <MyEvent>(); var source = sourceEvents[i].Event.To <MyEvent>(); CompareGuid(source.Payload.Values.First().Key, target.Payload.Values.First().Key); CompareGuid(source.Payload.GuidRaw, target.Payload.GuidRaw); CompareGuid(source.Payload.GuidNamed.Id, target.Payload.GuidNamed.Id); CompareGuid(source.Headers.GetGuid("Id"), target.Headers.GetGuid("Id")); Assert.Equal(Guid.Empty, target.Payload.GuidEmpty); } } }