internal FileLogRecord(FileLogRecordStream stream)
 {
     this.stream = stream;
 }
        // During WriteRestarArea, we truncate all records before the new base sequence number.
        // The new base sequence number is recorded in the restart-area record.
        // If truncate failed during WriteRestartArea, then the records before the new base seq number 
        // will still be present in the log.  During recovery, we will cleanup the log by removing these records.

        // Recovery steps -
        // Scan the log backwards
        // Stop when the last restart area is found
        // Truncate the log if needed

        private void Recover()
        {
            SequenceNumber first;
            SequenceNumber last;
            this.log.GetLogLimits(out first, out last);

            // Internal knowledge - if last < first, log is empty
            if (last < first)
                return;

            SequenceNumber sn = last;
            while (sn != SequenceNumber.Invalid && first <= sn && sn <= last)
            {
                FileLogRecordStream stream = new FileLogRecordStream(log, sn);
                if (stream.Header.IsRestartArea)
                {
                    this.lastRestartArea = stream.RecordSequenceNumber;

                    // if the base sequence number is different from
                    // the next undo lsn, then we crashed during or
                    // before truncate.  Perform the truncate now.
                    if (first < stream.Header.NextUndoLsn)
                    {

                        if (stream.Header.NextUndoLsn == SequenceNumber.Invalid)
                        {
                            // WriteRestartArea was called with LastSequenceNumber

                            if (first != stream.RecordSequenceNumber)
                            {
                                this.newBaseSeqNum = stream.RecordSequenceNumber;
                            }
                        }
                        else
                        {
                            this.newBaseSeqNum = stream.Header.NextUndoLsn;
                        }

                        // This method is called from the constructor.  So no need to take a write lock.
                        if (this.newBaseSeqNum != SequenceNumber.Invalid)
                        {
                            try
                            {
                                log.TruncatePrefix(this.newBaseSeqNum);
                                this.newBaseSeqNum = SequenceNumber.Invalid;
                            }
#pragma warning suppress 56500
                            catch (Exception exception)
                            {
                                // Truncate failed again.  We were unable to cleanup the log.  
                                this.truncateFailed = true;

                                if (Fx.IsFatal(exception)) throw;
                            }
                        }
                    }

                    break;
                }

                sn = stream.PrevLsn;
            }
        }
 internal FileLogRecord(FileLogRecordStream stream)
 {
     this.stream = stream;
 }
        public bool MoveNext()
        {
            if (this.disposed)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ObjectDisposed());
            }

            if (this.current == SequenceNumber.Invalid)
            {
                return(false);
            }

            if (!this.enumStarted)
            {
                this.enumStarted = true;
            }
            else
            {
                switch (this.logRecordEnum)
                {
                case LogRecordEnumeratorType.Next:
                    this.current = this.stream.NextLsn;
                    break;

                case LogRecordEnumeratorType.Previous:
                    this.current = this.stream.Header.PreviousLsn;
                    break;

                case LogRecordEnumeratorType.User:
                    this.current = this.stream.Header.NextUndoLsn;
                    break;
                }
            }

            SequenceNumber first;
            SequenceNumber last;

            log.GetLogLimits(out first, out last);
            if (this.current < first ||
                last < this.current ||
                this.current == SequenceNumber.Invalid)
            {
                this.record = null;
                return(false);
            }

            this.stream = new FileLogRecordStream(this.log, this.current);

            if (!this.enumRestartAreas && this.stream.Header.IsRestartArea)
            {
                if (this.logRecordEnum == LogRecordEnumeratorType.Next)
                {
                    // Move to the next record after restart area.
                    return(MoveNext());
                }
                else
                {
                    // We have hit a restart area.
                    // Restart areas have special values for prev and next undo in the header.
                    // Cannot enumerate further.
                    this.record = null;
                    return(false);
                }
            }

            this.record = new FileLogRecord(this.stream);
            return(true);
        }
        // During WriteRestarArea, we truncate all records before the new base sequence number.
        // The new base sequence number is recorded in the restart-area record.
        // If truncate failed during WriteRestartArea, then the records before the new base seq number
        // will still be present in the log.  During recovery, we will cleanup the log by removing these records.

        // Recovery steps -
        // Scan the log backwards
        // Stop when the last restart area is found
        // Truncate the log if needed

        private void Recover()
        {
            SequenceNumber first;
            SequenceNumber last;

            this.log.GetLogLimits(out first, out last);

            // Internal knowledge - if last < first, log is empty
            if (last < first)
            {
                return;
            }

            SequenceNumber sn = last;

            while (sn != SequenceNumber.Invalid && first <= sn && sn <= last)
            {
                FileLogRecordStream stream = new FileLogRecordStream(log, sn);
                if (stream.Header.IsRestartArea)
                {
                    this.lastRestartArea = stream.RecordSequenceNumber;

                    // if the base sequence number is different from
                    // the next undo lsn, then we crashed during or
                    // before truncate.  Perform the truncate now.
                    if (first < stream.Header.NextUndoLsn)
                    {
                        if (stream.Header.NextUndoLsn == SequenceNumber.Invalid)
                        {
                            // WriteRestartArea was called with LastSequenceNumber

                            if (first != stream.RecordSequenceNumber)
                            {
                                this.newBaseSeqNum = stream.RecordSequenceNumber;
                            }
                        }
                        else
                        {
                            this.newBaseSeqNum = stream.Header.NextUndoLsn;
                        }

                        // This method is called from the constructor.  So no need to take a write lock.
                        if (this.newBaseSeqNum != SequenceNumber.Invalid)
                        {
                            try
                            {
                                log.TruncatePrefix(this.newBaseSeqNum);
                                this.newBaseSeqNum = SequenceNumber.Invalid;
                            }
#pragma warning suppress 56500
                            catch (Exception exception)
                            {
                                // Truncate failed again.  We were unable to cleanup the log.
                                this.truncateFailed = true;

                                if (Fx.IsFatal(exception))
                                {
                                    throw;
                                }
                            }
                        }
                    }

                    break;
                }

                sn = stream.PrevLsn;
            }
        }