public void TryRecovery() { var journal = JournalService.GetJournalFilename(_connectionString, false); // no journal file, nothing to do if (string.IsNullOrEmpty(journal)) { return; } // if I can open journal file, test FINISH_POSITION this.OpenExclusiveFile(journal, (stream) => { // check if FINISH_POSITON is true using (var reader = new BinaryReader(stream)) { reader.Seek(JournalService.FINISH_POSITION); // if file is finish, datafile needs to be recovery. if not, // the failure ocurrs during write journal file but not finish - just discard it if (reader.ReadBoolean() == true) { this.DoRecovery(reader); } } // close stream for delete file stream.Close(); File.Delete(journal); }); // if I can't open, it's in use (and it's ok, there is a transaction executing in another process) }
public void CreateJournalFile(Action action) { if (!_connectionString.JournalEnabled) { action(); return; } var journal = JournalService.GetJournalFilename(_connectionString, true); // create journal file in EXCLUSIVE mode using (var stream = File.Open(journal, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { using (var writer = new BinaryWriter(stream)) { // first, allocate all journal file var total = (uint)_cache.GetDirtyPages().Count(); stream.SetLength(total * BasePage.PAGE_SIZE); uint index = 0; // for better performance, write first page at end of file and others in sequence order foreach (var page in _cache.GetDirtyPages()) { if (index == 0) { this.WritePageInJournal(total - 1, writer, page); } else { this.WritePageInJournal(index, writer, page); } index++; } // flush all data writer.Flush(); // mark header as finish writer.Seek(FINISH_POSITION); writer.Write(true); // mark as TRUE // flush last finish mark writer.Flush(); action(); } stream.Dispose(); File.Delete(journal); } }
public void CreateJournalFile(Action action) { if (!_connectionString.JournalEnabled) { action(); return; } var journal = JournalService.GetJournalFilename(_connectionString, true); // create journal file in EXCLUSIVE mode using (var stream = new FileStream(journal, FileMode.Create, FileAccess.ReadWrite, FileShare.None, BasePage.PAGE_SIZE)) { using (var writer = new BinaryWriter(stream)) { // first, allocate all journal file var total = (uint)_cache.GetDirtyPages().Count(); stream.SetLength(total * BasePage.PAGE_SIZE); // write all dirty pages in sequence on journal file foreach (var page in _cache.GetDirtyPages()) { this.WritePageInJournal(writer, page); } // flush all data writer.Flush(); // mark header as finish stream.Seek(FINISH_POSITION, SeekOrigin.Begin); writer.Write(true); // mark as TRUE // flush last finish mark writer.Flush(); action(); } stream.Dispose(); File.Delete(journal); } }
internal TransactionService(DiskService disk, CacheService cache, JournalService journal) { _disk = disk; _cache = cache; _journal = journal; }