Пример #1
0
        /// <summary>
        /// This begins an async commit and starts a new transaction immediately.
        /// The current transaction is considered completed in memory but not yet
        /// committed to disk. This *must* be completed by calling EndAsyncCommit.
        /// </summary>
        public LowLevelTransaction BeginAsyncCommitAndStartNewTransaction()
        {
            if (Flags != TransactionFlags.ReadWrite)
            {
                ThrowReadTranscationCannotDoAsyncCommit();
            }
            if (_asyncCommitNextTransaction != null)
            {
                ThrowAsyncCommitAlreadyCalled();
            }

            // we have to check the state before we complete the transaction
            // because that would change whether we need to write to the journal
            var writeToJournalIsRequired = WriteToJournalIsRequired();

            CommitStage1_CompleteTransaction();

            var nextTx = new LowLevelTransaction(this,
                                                 writeToJournalIsRequired ? Id + 1 : Id
                                                 );

            _asyncCommitNextTransaction = nextTx;
            AsyncCommit = writeToJournalIsRequired
                  ? Task.Run(() => { CommitStage2_WriteToJournal(); return(true); })
                  : NoWriteToJournalRequiredTask;

            try
            {
                _env.IncrementUsageOnNewTransaction();
                _env.ActiveTransactions.Add(nextTx);
                _env.WriteTransactionStarted();

                return(nextTx);
            }
            catch (Exception)
            {
                // failure here means that we'll try to complete the current transaction normaly
                // then throw as if commit was called normally and the next transaction failed

                _env.DecrementUsageOnTransactionCreationFailure();

                EndAsyncCommit();

                AsyncCommit = null;

                _disposed |= TxState.Errored;

                throw;
            }
        }
Пример #2
0
        public void Dispose()
        {
            if (_trees != null)
            {
                foreach (var tree in _trees)
                {
                    tree.Value?.Dispose();
                }
            }

            if (_multiValueTrees != null)
            {
                foreach (var item in _multiValueTrees)
                {
                    item.Value?.Dispose();
                    item.Key.Item1?.Dispose();
                }
            }

            if (_tables != null)
            {
                foreach (var table in _tables)
                {
                    table.Value?.Dispose();
                }
            }

            if (_globalFixedSizeTree != null)
            {
                foreach (var tree in _globalFixedSizeTree)
                {
                    tree.Value?.Dispose();
                }
            }

            _lowLevelTransaction?.Dispose();

            _lowLevelTransaction = null;
        }
Пример #3
0
        private LowLevelTransaction(LowLevelTransaction previous, long txId)
        {
            // this is meant to be used with transaction merging only
            // so it makes a lot of assumptions about the usage scenario
            // and what it can do

            Debug.Assert(previous.Flags == TransactionFlags.ReadWrite);

            var env = previous._env;

            env.Options.AssertNoCatastrophicFailure();

            FlushInProgressLockTaken = previous.FlushInProgressLockTaken;
            CurrentTransactionHolder = previous.CurrentTransactionHolder;
            TxStartTime        = DateTime.UtcNow;
            DataPager          = env.Options.DataPager;
            _env               = env;
            _journal           = env.Journal;
            _id                = txId;
            _freeSpaceHandling = previous._freeSpaceHandling;
            _allocator         = previous._allocator;

            _disposeAllocator          = previous._disposeAllocator;
            previous._disposeAllocator = false;

            PersistentContext = previous.PersistentContext;
            Flags             = TransactionFlags.ReadWrite;

            _pagerStates = new HashSet <PagerState>(ReferenceEqualityComparer <PagerState> .Default);

            JournalFiles = previous.JournalFiles;

            foreach (var journalFile in JournalFiles)
            {
                journalFile.AddRef();
            }

            var pagers = new HashSet <AbstractPager>();

            foreach (var scratchAndDataPagerState in previous._pagerStates)
            {
                // in order to avoid "dragging" pager state ref on non active scratch - we will not copy disposed scratches from previous async tx. RavenDB-6766
                if (scratchAndDataPagerState.DiscardOnTxCopy)
                {
                    continue;
                }

                // copy the "current pager" which is the last pager used, and by that do not "drag" old non used pager state refs to the next async commit (i.e. older views of data file). RavenDB-6949
                var currentPager = scratchAndDataPagerState.CurrentPager;
                if (pagers.Add(currentPager) == false)
                {
                    continue;
                }

                var state = currentPager.PagerState;
                state.AddRef();
                _pagerStates.Add(state);
            }


            EnsureNoDuplicateTransactionId(_id);

            // we can reuse those instances, not calling Reset on the pool
            // because we are going to need to scratch buffer pool
            _dirtyOverflowPages = previous._dirtyOverflowPages;
            _dirtyOverflowPages.Clear();

            _scratchPagesTable = _env.WriteTransactionPool.ScratchPagesReadyForNextTx;

            foreach (var kvp in previous._scratchPagesTable)
            {
                if (previous._dirtyPages.Contains(kvp.Key))
                {
                    _scratchPagesTable.Add(kvp.Key, kvp.Value);
                }
            }
            previous._scratchPagesTable.Clear();
            _env.WriteTransactionPool.ScratchPagesInUse          = _scratchPagesTable;
            _env.WriteTransactionPool.ScratchPagesReadyForNextTx = previous._scratchPagesTable;

            _dirtyPages = previous._dirtyPages;
            _dirtyPages.Clear();

            _freedPages          = new HashSet <long>(NumericEqualityComparer.BoxedInstanceInt64);
            _unusedScratchPages  = new List <PageFromScratchBuffer>();
            _transactionPages    = new HashSet <PageFromScratchBuffer>(PageFromScratchBufferEqualityComparer.Instance);
            _pagesToFreeOnCommit = new Stack <long>();

            _state = previous._state.Clone();

            _pageLocator = PersistentContext.AllocatePageLocator(this);
            InitializeRoots();
            InitTransactionHeader();
        }
Пример #4
0
 public Transaction(LowLevelTransaction lowLevelTransaction)
 {
     _lowLevelTransaction = lowLevelTransaction;
 }
Пример #5
0
 public Transaction(LowLevelTransaction lowLevelTransaction)
 {
     _lowLevelTransaction             = lowLevelTransaction;
     _lowLevelTransaction.Transaction = this;
 }
Пример #6
0
 public static FixedSizeTreePage GetReadOnlyFixedSizeTreePage(this LowLevelTransaction tx, long pageNumber)
 {
     return(tx.GetPage(pageNumber).ToFixedSizeTreePage());
 }