private void RollForwardRecover() { // The list of all journal files, var journalFilesList = new List <JournalSummary>(); // Scan the journal path for any journal files. for (int i = 10; i < 74; ++i) { string journalFn = GetJournalFileName(i); string f = FileSystem.CombinePath(JournalPath, journalFn); // If the journal exists, create a summary of the journal if (FileSystem.FileExists(f)) { if (ReadOnly) { throw new IOException( "Journal file " + f + " exists for a read-only session. " + "There may not be any pending journals for a Read-only session."); } var jf = new JournalFile(this, FileSystem, f, ReadOnly); // Open the journal file for recovery. This will set various // information about the journal such as the last check point and the // id of the journal file. JournalSummary summary = jf.OpenForRecovery(); // If the journal can be recovered from. if (summary.CanBeRecovered) { Context.OnInformation(String.Format("Journal '{0}' found: can be recovered", jf)); journalFilesList.Add(summary); } else { Context.OnInformation(String.Format("Deleting journal '{0}': nothing to recover", jf)); // Otherwise close and delete it jf.CloseAndDelete(); } } } // Sort the journal file list from oldest to newest. The oldest journals // are recovered first. journalFilesList.Sort(new JournalSummaryComparer()); long lastJournalNumber = -1; // Persist the journals for (int i = 0; i < journalFilesList.Count; ++i) { var summary = journalFilesList[i]; // Check the resources for this summary var resList = summary.Resources; foreach (string resourceName in resList) { // This puts the resource into the hash map. CreateResource(resourceName); } // Assert that we are recovering the journals input the correct order JournalFile jf = summary.JournalFile; if (jf.JournalNumber < lastJournalNumber) { throw new InvalidOperationException("Assertion failed, sort failed."); } lastJournalNumber = jf.JournalNumber; Context.OnInformation(String.Format("Recovering '{0}' (8 .. {1})", jf, summary.LastCheckPoint)); jf.Persist(8, summary.LastCheckPoint); // Then close and delete. jf.CloseAndDelete(); // Check the resources for this summary and close them foreach (var resourceName in resList) { var resource = (ResourceBase)CreateResource(resourceName); // When we finished, make sure the resource is closed again // Close the resource resource.PersistClose(); // Post recover notification resource.OnPostRecover(); } } }
internal JournalSummary OpenForRecovery() { if (IsOpen) throw new IOException(String.Format("Journal file '{0}' is already open.", FilePath)); if (!FileSystem.FileExists(FilePath)) throw new IOException(String.Format("Journal file '{0}' does not exists.", FilePath)); // Open the random access file to this journal File = new StreamFile(FileSystem, FilePath, ReadOnly); IsOpen = true; // Create the summary object (by default, not recoverable). var summary = new JournalSummary(this); long endPointer = File.Length; // If end_pointer < 8 then can't recover this journal if (endPointer < 8) { return summary; } // The input stream. using (var reader = new BinaryReader(File.FileStream, Encoding.Unicode)) { // Set the journal number for this JournalNumber = reader.ReadInt64(); long position = 8; var checkpointResList = new List<string>(); // Start scan while (true) { // If we can't Read 12 bytes ahead, return the summary if (position + 12 > endPointer) { return summary; } long type = reader.ReadInt64(); int size = reader.ReadInt32(); position = position + size + 12; bool skipBody = true; // If checkpoint reached then we are recoverable if (type == 100) { summary.LastCheckPoint = position; summary.CanBeRecovered = true; // Add the resources input this check point foreach (var checkpoint in checkpointResList) { summary.Resources.Add(checkpoint); } // And clear the temporary list. checkpointResList.Clear(); } // If end reached, or type is not understood then return else if (position >= endPointer || type < 1 || type > 7) { return summary; } // If we are resource type, then load the resource if (type == 2) { // We don't skip body for this type, we Read the content skipBody = false; long id = reader.ReadInt64(); int strLen = reader.ReadInt32(); StringBuilder str = new StringBuilder(strLen); for (int i = 0; i < strLen; ++i) { str.Append(reader.ReadChar()); } var resourceName = str.ToString(); checkpointResList.Add(resourceName); } if (skipBody) reader.BaseStream.Seek(size, SeekOrigin.Current); } } }
internal JournalSummary OpenForRecovery() { if (IsOpen) { throw new IOException(String.Format("Journal file '{0}' is already open.", FilePath)); } if (!FileSystem.FileExists(FilePath)) { throw new IOException(String.Format("Journal file '{0}' does not exists.", FilePath)); } // Open the random access file to this journal File = new StreamFile(FileSystem, FilePath, ReadOnly); IsOpen = true; // Create the summary object (by default, not recoverable). var summary = new JournalSummary(this); long endPointer = File.Length; // If end_pointer < 8 then can't recover this journal if (endPointer < 8) { return(summary); } // The input stream. using (var reader = new BinaryReader(File.FileStream, Encoding.Unicode)) { // Set the journal number for this JournalNumber = reader.ReadInt64(); long position = 8; var checkpointResList = new List <string>(); // Start scan while (true) { // If we can't Read 12 bytes ahead, return the summary if (position + 12 > endPointer) { return(summary); } long type = reader.ReadInt64(); int size = reader.ReadInt32(); position = position + size + 12; bool skipBody = true; // If checkpoint reached then we are recoverable if (type == 100) { summary.LastCheckPoint = position; summary.CanBeRecovered = true; // Add the resources input this check point foreach (var checkpoint in checkpointResList) { summary.Resources.Add(checkpoint); } // And clear the temporary list. checkpointResList.Clear(); } // If end reached, or type is not understood then return else if (position >= endPointer || type < 1 || type > 7) { return(summary); } // If we are resource type, then load the resource if (type == 2) { // We don't skip body for this type, we Read the content skipBody = false; long id = reader.ReadInt64(); int strLen = reader.ReadInt32(); StringBuilder str = new StringBuilder(strLen); for (int i = 0; i < strLen; ++i) { str.Append(reader.ReadChar()); } var resourceName = str.ToString(); checkpointResList.Add(resourceName); } if (skipBody) { reader.BaseStream.Seek(size, SeekOrigin.Current); } } } }