public void Rollback()
        {
            // here we allow rolling back of errored transaction
            if (_disposed.HasFlag(TxState.Disposed))
            {
                ThrowObjectDisposed();
            }


            if (Committed || RolledBack || Flags != (TransactionFlags.ReadWrite))
            {
                return;
            }

            ValidateReadOnlyPages();

            foreach (var pageFromScratch in _transactionPages)
            {
                _env.ScratchBufferPool.Free(this, pageFromScratch.ScratchFileNumber, pageFromScratch.PositionInScratchBuffer, null);
            }

            foreach (var pageFromScratch in _unusedScratchPages)
            {
                _env.ScratchBufferPool.Free(this, pageFromScratch.ScratchFileNumber, pageFromScratch.PositionInScratchBuffer, null);
            }

            // release scratch file page allocated for the transaction header
            Allocator.Release(ref _txHeaderMemory);

            using (_env.PreventNewReadTransactions())
            {
                _env.ScratchBufferPool.UpdateCacheForPagerStatesOfAllScratches();
                _env.Journal.UpdateCacheForJournalSnapshots();
            }

            RolledBack = true;
        }