Esempio n. 1
0
        /// <summary>
        /// Create a transaction
        /// </summary>
        /// <param name="transactionsList">The optional transactions to see this transaction with.</param>
        /// <param name="isolated">Whether this is an isolated transaction.</param>
        /// <param name="callerMemberName"></param>
        /// <param name="callerLineNumber"></param>
        /// <returns></returns>
        /// <remarks>
        /// An isolated transaction is one which sits away from any other current transactions. One could say have a transaction
        /// being currently active but the code needs to create a transaction for which every transaction is committed by the time the commit has been executed.
        /// This wouldn't happen unless it were an isolated transaction.
        /// Whenever a transaction is created, the transaction depth is incremented. For non isolated transactions if there is already a transaction in play then any new transactions are appended to it.
        /// </remarks>
        public static Transaction Create(TransactionsList transactionsList = default, bool isolated = false, [CallerMemberName] string callerMemberName = default, [CallerLineNumber] int callerLineNumber = default)
        {
            var id = Interlocked.Increment(ref _idSeed);

            if (IsLoggingEnabled.Value)
            {
                Logging.Instance.LogInformation(
                    "Transaction {id} Created, isolated:{isolated},thread:{threadId},with transactions:{withTransactions},transaction depth:{transactionDepth}",
                    id, isolated, Thread.CurrentThread.ManagedThreadId, (transactionsList != default),
                    Model.TransactionDepth);
            }

            Model.Lock.EnterWriteLock();

            try
            {
                ++Model.TransactionDepth;

                // let us check that if the current instance is isolated then any requests whilst active should be isolated as well
                if (!isolated && Model.TransactionDepth > 1 && Model.Instance.Isolated)
                {
                    isolated = true;
                    Logging.Instance.LogWarning("Transaction {id} created inside an existing isolated transaction.Promoting to isolated as well. Called by {calledMember}, {calledLineNumber}", id, callerMemberName, callerLineNumber);
                }

                var transaction = new Transaction(id, transactionsList, isolated);

                Model.SaveInstance();

                Model.Instance = transaction;

                return(transaction);
            }
            finally
            {
                Model.Lock.ExitWriteLock();
            }
        }
Esempio n. 2
0
 private Transaction(int id, TransactionsList transactionsList, bool isolated = false)
 {
     _id              = id;
     Isolated         = isolated;
     TransactionsList = transactionsList ?? new TransactionsList();
 }
Esempio n. 3
0
 private Transaction(int id)
 {
     _id = id;
     TransactionsList = new TransactionsList();
 }
Esempio n. 4
0
 /// <summary>
 /// Add a transaction.
 /// </summary>
 /// <param name="action"></param>
 public void Add(Action action)
 {
     VerifyTransaction();
     TransactionsList.Add(action);
 }
Esempio n. 5
0
        /// <summary>
        /// Commit any transactions.
        /// </summary>
        /// <remarks>
        /// If this is an isolated transaction the transactions are immediately committed.
        /// If not isolated then if the transaction depth is "1" then the transactions are added to a commit queue. If the commit queue isn't currently being processed then
        /// this transactions are then committed. If the commit queue is active then a prior commit call will result in the transactions ultimately being 'committed'.
        /// </remarks>
        public void Commit()
        {
            if (IsLoggingEnabled.Value)
            {
                Logging.Instance.LogInformation(
                    "Transaction {id} Commit starting,thread:{threadId},no transactions:{noTransactions},transaction depth:{transactionDepth}", _id,
                    Thread.CurrentThread.ManagedThreadId, TransactionsList.Count, Model.TransactionDepth);
            }

            var commit = false;


            Model.Lock.EnterWriteLock();

            try
            {
                --Model.TransactionDepth;

                // if not isolated and there are some transactions then add them to the commit queue
                if (!Isolated && TransactionsList.Count > 0)
                {
                    Model.CommitQueue.Add(TransactionsList);
                }

                // if isolated or depth of transactions is back at ground zero then we need to commit
                if (Isolated || Model.TransactionDepth == 0)
                {
                    commit = true;
                }

                Model.RestoreInstance();
            }
            finally
            {
                Model.Lock.ExitWriteLock();
            }

            // should we commit transactions?
            if (commit)
            {
                try
                {
                    // If this is an isolated transaction, then we apply immediately
                    if (Isolated)
                    {
                        TransactionsList.Apply();
                    }
                    else
                    {
                        // This will return immediately if higher level commit currently in play
                        Model.CommitQueue.Commit();
                    }
                }
                catch (Exception exception)
                {
                    Logging.Instance.LogError(exception, "Transaction {id} Commit failure", _id);

                    // mark as complete, so as to not generate a duff error
                    _completed = true;
                    throw;
                }
            }

            // indicate we are done
            _completed = true;

            if (IsLoggingEnabled.Value)
            {
                Logging.Instance.LogInformation(
                    "Transaction {id} Commit complete,thread:{threadId},transaction depth:{transactionDepth}", _id,
                    Thread.CurrentThread.ManagedThreadId, Model.TransactionDepth);
            }
        }
 /// <summary>
 /// Create a new transactions list from a provided <see cref="TransactionsList"/>
 /// </summary>
 /// <param name="transactionsList"></param>
 public TransactionsList(TransactionsList transactionsList)
 {
     _transactions = transactionsList != null ? new List <Action>(transactionsList._transactions) : new List <Action>();
 }