internal SequenceNumber Append(IList <ArraySegment <byte> > data,
                                       SequenceNumber nextUndoRecord,
                                       SequenceNumber previousRecord,
                                       bool forceFlush)
        {
            TruncateIfNecessary();

            bool lockHeld = false;

            try
            {
                try { }
                finally
                {
                    appendLock.AcquireReaderLock(-1);
                    lockHeld = true;
                }
                using (AppendHelper helper = new AppendHelper(
                           data,
                           previousRecord,
                           nextUndoRecord,
                           false))
                {
                    return(log.AppendRecord(helper.Blobs, forceFlush));
                }
            }
            finally
            {
                if (lockHeld)
                {
                    appendLock.ReleaseReaderLock();
                }
            }
        }
示例#2
0
        internal SequenceNumber WriteRestartAreaInternal(
            IList<ArraySegment<byte>> data,
            SequenceNumber newBaseSeqNum)
        {

            if (data == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentNull("data"));
            }

            TruncateIfNecessary();

            bool lockHeld = false;
            try
            {
                try { }
                finally
                {
                    appendLock.AcquireWriterLock(-1);
                    lockHeld = true;
                }

                SequenceNumber sn;
                AppendHelper helper;
                bool lastSeqNum, firstSeqNum;

                lastSeqNum = newBaseSeqNum == this.LastSequenceNumber;
                firstSeqNum = newBaseSeqNum == this.BaseSequenceNumber;

                if (lastSeqNum)
                {
                    // We dont know the new base sequence number.
                    // It will be the sequence number we get from append.
                    helper = new AppendHelper(data,
                                            this.lastRestartArea,
                                            SequenceNumber.Invalid,
                                            true);
                }
                else
                {
                    if (!firstSeqNum)
                    {
                        ValidateSequenceNumber(newBaseSeqNum);

                        // Validate newBaseSequenceNumber by reading the corresponding record.
                        int cbData = 1;
                        byte[] record;
                        int recordSize;
                        SequenceNumber prev, next;

                        // Sequence number validation checks if the Seq Num > BSN and Seq Num < LSN. 
                        // Now we validate if Seq Number is a valid number in this sequence.
                        try
                        {
                            this.log.ReadRecordPrefix(newBaseSeqNum, out record, ref cbData, out recordSize, out prev, out next);
                        }
                        catch (ArgumentException exception)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentOutOfRange(SR.Argument_TailInvalid, exception));
                        }
                    }

                    helper = new AppendHelper(data,
                                            this.lastRestartArea,
                                            newBaseSeqNum,
                                            true);
                }

                // If there is a failure betweeen append and truncate,
                // then the log will be in an inconsistent state.  To
                // solve this, we write the new base sequence number in
                // the header.  During recovery from failure, we will find
                // the restart area and truncate the log.

                using (helper)
                {
                    // No need for a reader appendLock, since WriteRestartAreaInternal is under a lock.
                    sn = this.log.AppendRecord(helper.Blobs, true);
                }

                this.lastRestartArea = sn;

                if (firstSeqNum)
                {
                    return sn;
                }

                if (lastSeqNum)
                {
                    newBaseSeqNum = sn;
                }

                try
                {
                    log.TruncatePrefix(newBaseSeqNum);
                }
#pragma warning suppress 56500
                catch (Exception exception)
                {
                    this.newBaseSeqNum = newBaseSeqNum;
                    this.truncateFailed = true;

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

                return sn;
            }
            finally
            {
                if (lockHeld)
                {
                    appendLock.ReleaseWriterLock();
                }
            }
        }
示例#3
0
        internal SequenceNumber Append(IList<ArraySegment<byte>> data,
                                        SequenceNumber nextUndoRecord,
                                        SequenceNumber previousRecord,
                                        bool forceFlush)
        {
            TruncateIfNecessary();

            bool lockHeld = false;
            try
            {
                try { }
                finally
                {
                    appendLock.AcquireReaderLock(-1);
                    lockHeld = true;
                }
                using (AppendHelper helper = new AppendHelper(
                                                    data,
                                                    previousRecord,
                                                    nextUndoRecord,
                                                    false))
                {

                    return log.AppendRecord(helper.Blobs, forceFlush);
                }
            }
            finally
            {
                if (lockHeld)
                {
                    appendLock.ReleaseReaderLock();
                }
            }
        }
        internal SequenceNumber WriteRestartAreaInternal(
            IList <ArraySegment <byte> > data,
            SequenceNumber newBaseSeqNum)
        {
            if (data == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentNull("data"));
            }

            TruncateIfNecessary();

            bool lockHeld = false;

            try
            {
                try { }
                finally
                {
                    appendLock.AcquireWriterLock(-1);
                    lockHeld = true;
                }

                SequenceNumber sn;
                AppendHelper   helper;
                bool           lastSeqNum, firstSeqNum;

                lastSeqNum  = newBaseSeqNum == this.LastSequenceNumber;
                firstSeqNum = newBaseSeqNum == this.BaseSequenceNumber;

                if (lastSeqNum)
                {
                    // We dont know the new base sequence number.
                    // It will be the sequence number we get from append.
                    helper = new AppendHelper(data,
                                              this.lastRestartArea,
                                              SequenceNumber.Invalid,
                                              true);
                }
                else
                {
                    if (!firstSeqNum)
                    {
                        ValidateSequenceNumber(newBaseSeqNum);

                        // Validate newBaseSequenceNumber by reading the corresponding record.
                        int            cbData = 1;
                        byte[]         record;
                        int            recordSize;
                        SequenceNumber prev, next;

                        // Sequence number validation checks if the Seq Num > BSN and Seq Num < LSN.
                        // Now we validate if Seq Number is a valid number in this sequence.
                        try
                        {
                            this.log.ReadRecordPrefix(newBaseSeqNum, out record, ref cbData, out recordSize, out prev, out next);
                        }
                        catch (ArgumentException exception)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ArgumentOutOfRange(SR.Argument_TailInvalid, exception));
                        }
                    }

                    helper = new AppendHelper(data,
                                              this.lastRestartArea,
                                              newBaseSeqNum,
                                              true);
                }

                // If there is a failure betweeen append and truncate,
                // then the log will be in an inconsistent state.  To
                // solve this, we write the new base sequence number in
                // the header.  During recovery from failure, we will find
                // the restart area and truncate the log.

                using (helper)
                {
                    // No need for a reader appendLock, since WriteRestartAreaInternal is under a lock.
                    sn = this.log.AppendRecord(helper.Blobs, true);
                }

                this.lastRestartArea = sn;

                if (firstSeqNum)
                {
                    return(sn);
                }

                if (lastSeqNum)
                {
                    newBaseSeqNum = sn;
                }

                try
                {
                    log.TruncatePrefix(newBaseSeqNum);
                }
#pragma warning suppress 56500
                catch (Exception exception)
                {
                    this.newBaseSeqNum  = newBaseSeqNum;
                    this.truncateFailed = true;

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

                return(sn);
            }
            finally
            {
                if (lockHeld)
                {
                    appendLock.ReleaseWriterLock();
                }
            }
        }