public TransactionService GetTransaction(bool create, bool queryOnly, out bool isNew) { var transaction = _slot.Value; if (create && transaction == null) { isNew = true; bool alreadyLock; // must lock _transaction before work with _transactions (GetInitialSize use _transactions) lock (_transactions) { if (_transactions.Count >= MAX_OPEN_TRANSACTIONS) { throw new LiteException(0, "Maximum number of transactions reached"); } var initialSize = this.GetInitialSize(); // check if current thread contains any transaction alreadyLock = _transactions.Values.Any(x => x.ThreadID == Environment.CurrentManagedThreadId); transaction = new TransactionService(_header, _locker, _disk, _walIndex, initialSize, this, queryOnly); // add transaction to execution transaction dict _transactions[transaction.TransactionID] = transaction; } // enter in lock transaction after release _transaction lock if (alreadyLock == false) { _locker.EnterTransaction(); } // do not store in thread query-only transaction if (queryOnly == false) { _slot.Value = transaction; } } else { isNew = false; } return(transaction); }
public TransactionService(HeaderPage header, LockService locker, DiskService disk, WalIndexService walIndex, int maxTransactionSize, Action <uint> done) { // retain instances _header = header; _locker = locker; _disk = disk; _walIndex = walIndex; _maxTransactionSize = maxTransactionSize; _done = done; // create new transactionID _transactionID = walIndex.NextTransactionID(); _startTime = DateTime.UtcNow; _reader = _disk.GetReader(); // enter transaction locker to avoid 2 transactions in same thread _locker.EnterTransaction(); }