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();
                }
            }
        }
示例#2
0
        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);
                }

            }
        }
示例#3
0
        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);
                    }
                }
            }
        }