Esempio n. 1
0
 private bool WriteToJournalIsRequired()
 {
     return(_dirtyPages.Count > 0 ||
            _freedPages.Count > 0
            // nothing changed in this transaction
            // allow call to writeToJournal for flushing lazy tx
            || (IsLazyTransaction == false && _journal?.HasDataInLazyTxBuffer() == true));
 }
Esempio n. 2
0
        public void Commit()
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("Transaction");
            }

            if (Flags != (TransactionFlags.ReadWrite))
            {
                return; // nothing to do
            }
            if (Committed)
            {
                throw new InvalidOperationException("Cannot commit already committed transaction.");
            }

            if (RolledBack)
            {
                throw new InvalidOperationException("Cannot commit rolled-back transaction.");
            }

            while (_pagesToFreeOnCommit.Count > 0)
            {
                FreePage(_pagesToFreeOnCommit.Pop());
            }
            _txHeader->LastPageNumber = _state.NextPageNumber - 1;
            _state.Root.CopyTo(&_txHeader->Root);

            _txHeader->TxMarker |= TransactionMarker.Commit;

            var totalNumberOfAllocatedPages = _allocatedPagesInTransaction + _overflowPagesInTransaction;

            if (totalNumberOfAllocatedPages > 0 || // nothing changed in this transaction
                                                   // allow call to writeToJournal for flushing lazy tx
                (IsLazyTransaction == false && _journal?.HasDataInLazyTxBuffer() == true))
            {
                // In the case of non-lazy transactions, we must flush the data from older lazy transactions
                // to ensure the sequentiality of the data.
                var numberOfWrittenPages = _journal.WriteToJournal(this, totalNumberOfAllocatedPages + PagesTakenByHeader);
                FlushedToJournal = true;

                if (_requestedCommitStats != null)
                {
                    _requestedCommitStats.NumberOfModifiedPages      = totalNumberOfAllocatedPages + PagesTakenByHeader;
                    _requestedCommitStats.NumberOfPagesWrittenToDisk = numberOfWrittenPages;
                }
            }

            // an exception being throw after the transaction has been committed to disk
            // will corrupt the in memory state, and require us to restart (and recover) to
            // be in a valid state
            try
            {
                ValidateAllPages();

                // release scratch file page allocated for the transaction header
                _env.ScratchBufferPool.Free(_transactionHeaderPage.ScratchFileNumber, _transactionHeaderPage.PositionInScratchBuffer, null);

                Committed = true;
                _env.TransactionAfterCommit(this);
            }
            catch (Exception e)
            {
                _env.CatastrophicFailure = ExceptionDispatchInfo.Capture(e);

                throw;
            }
            OnCommit?.Invoke(this);
        }