private Persist ( long start, long end ) : void | ||
start | long | |
end | long | |
return | void |
private void Execute() { bool localFinished = false; while (!localFinished) { List <JournalFile> toProcess = null; lock (system.topJournalLock) { if (system.journalArchives.Count > 0) { toProcess = new List <JournalFile>(); toProcess.AddRange(system.journalArchives); } } if (toProcess == null) { // Nothing to process so wait lock (this) { if (!finished) { #if PCL try { Monitor.Wait(this); } catch (OperationCanceledException) { } #else try { Monitor.Wait(this); } catch (ThreadInterruptedException) { /* ignore */ } #endif } } } else if (toProcess.Count > 0) { // Something to process, so go ahead and process the journals, int sz = toProcess.Count; // For all journals for (int i = 0; i < sz; ++i) { // Pick the lowest journal to persist JournalFile jf = toProcess[i]; try { // Persist the journal jf.Persist(8, jf.Length); // Close and then delete the journal file jf.CloseAndDelete(); } catch (IOException e) { system.Context.OnError(String.Format("Error persisting journal '{0}", jf), e); // If there is an error persisting the best thing to do is // finish lock (this) { finished = true; } } } } lock (this) { localFinished = finished; // Remove the journals that we have just persisted. if (toProcess != null) { lock (system.topJournalLock) { int sz = toProcess.Count; for (int i = 0; i < sz; ++i) { system.journalArchives.RemoveAt(0); } } } // Notify any threads waiting Monitor.PulseAll(this); } } lock (this) { actually_finished = true; Monitor.PulseAll(this); } }
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(); } } }