/// <summary> /// Get journal pages and override all into datafile /// </summary> public void Recovery() { _log.Write(Logger.Recovery, "initializing recovery mode"); using (_locker.Write()) { // double check in header need recovery (could be already recover from another thread) var header = BasePage.ReadPage(_disk.ReadPage(0)) as HeaderPage; if (header.Recovery == false) { return; } // read all journal pages foreach (var buffer in _disk.ReadJournal(header.LastPageID)) { // read pageID (first 4 bytes) var pageID = BitConverter.ToUInt32(buffer, 0); _log.Write(Logger.Recovery, "recover page #{0:0000}", pageID); // write in stream (encrypt if datafile is encrypted) _disk.WritePage(pageID, _crypto == null || pageID == 0 ? buffer : _crypto.Encrypt(buffer)); } // shrink datafile _disk.ClearJournal(header.LastPageID); } }
/// <summary> /// Try recovery journal file (if exists). Restore original datafile /// Journal file are NOT encrypted (even when datafile are encrypted) /// </summary> public void Recovery() { var fileSize = _disk.FileLength; // read all journal pages foreach (var buffer in _disk.ReadJournal()) { // read pageID (first 4 bytes) var pageID = BitConverter.ToUInt32(buffer, 0); _log.Write(Logger.RECOVERY, "recover page #{0:0000}", pageID); // if header, read all byte (to get original filesize) if (pageID == 0) { var header = (HeaderPage)BasePage.ReadPage(buffer); fileSize = BasePage.GetSizeOfPages(header.LastPageID + 1); } // write in stream (encrypt if datafile is encrypted) _disk.WritePage(pageID, _crypto == null || pageID == 0 ? buffer : _crypto.Encrypt(buffer)); } _log.Write(Logger.RECOVERY, "resize datafile to {0} bytes", fileSize); // redim filesize if grow more than original before rollback _disk.SetLength(fileSize); // empty journal file _disk.ClearJournal(); }