Esempio n. 1
0
        protected override void DoBegin(object transaction, ITransactionDefinition definition)
        {
            if (definition.IsolationLevel != AbstractTransactionDefinition.ISOLATION_DEFAULT)
            {
                throw new InvalidIsolationLevelException("AMQP does not support an isolation level concept");
            }

            var txObject = (RabbitTransactionObject)transaction;
            RabbitResourceHolder resourceHolder = null;

            try
            {
                resourceHolder = ConnectionFactoryUtils.GetTransactionalResourceHolder(ConnectionFactory, true);
                _logger?.LogDebug("Created AMQP transaction on channel [" + resourceHolder.GetChannel() + "]");

                txObject.ResourceHolder = resourceHolder;
                txObject.ResourceHolder.SynchronizedWithTransaction = true;
                var timeout = DetermineTimeout(definition);
                if (timeout != AbstractTransactionDefinition.TIMEOUT_DEFAULT)
                {
                    txObject.ResourceHolder.SetTimeoutInSeconds(timeout);
                }

                TransactionSynchronizationManager.BindResource(ConnectionFactory, txObject.ResourceHolder);
            }
            catch (AmqpException ex)
            {
                if (resourceHolder != null)
                {
                    ConnectionFactoryUtils.ReleaseResources(resourceHolder);
                }

                throw new CannotCreateTransactionException("Could not create AMQP transaction", ex);
            }
        }
Esempio n. 2
0
 /// <summary>
 /// Resume this synchronization.
 /// </summary>
 /// <remarks>
 ///     <p>
 /// Supposed to unbind resources from
 /// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager"/>
 /// if managing any.
 /// </p>
 /// </remarks>
 public override void Resume()
 {
     if (holderActive)
     {
         TransactionSynchronizationManager.BindResource(dbProvider, connectionHolder);
     }
 }
Esempio n. 3
0
 public override void Resume()
 {
     if (holderActive)
     {
         TransactionSynchronizationManager.BindResource(resourceKey, resourceHolder);
     }
 }
        /// <summary>
        /// Begin a new transaction with the given transaction definition.
        /// </summary>
        /// <param name="transaction">
        /// Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.
        /// </param>
        /// <param name="definition">
        /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing
        /// propagation behavior, isolation level, timeout etc.
        /// </param>
        /// <remarks>
        /// Does not have to care about applying the propagation behavior,
        /// as this has already been handled by this abstract manager.
        /// </remarks>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of creation or system errors.
        /// </exception>
        protected override void DoBegin(object transaction, ITransactionDefinition definition)
        {
            DbProviderTransactionObject txMgrStateObject =
                (DbProviderTransactionObject)transaction;
            IDbConnection con = null;

            if (dbProvider == null)
            {
                throw new ArgumentException("DbProvider is required to be set on AdoPlatformTransactionManager");
            }

            try
            {
                if (txMgrStateObject.ConnectionHolder == null || txMgrStateObject.ConnectionHolder.SynchronizedWithTransaction)
                {
                    IDbConnection newCon = DbProvider.CreateConnection();
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Acquired Connection [" + newCon + ", " + newCon.ConnectionString + "] for ADO.NET transaction");
                    }
                    newCon.Open();

                    //TODO isolation level mgmt - will need to abstract out SQL used to specify this in DbMetaData
                    //MSDN docs...
                    //With one exception, you can switch from one isolation level to another at any time during a transaction. The exception occurs when changing from any isolation level to SNAPSHOT isolation


                    //IsolationLevel previousIsolationLevel =

                    IDbTransaction newTrans = newCon.BeginTransaction(definition.TransactionIsolationLevel);

                    txMgrStateObject.SetConnectionHolder(new ConnectionHolder(newCon, newTrans), true);
                }
                txMgrStateObject.ConnectionHolder.SynchronizedWithTransaction = true;
                con = txMgrStateObject.ConnectionHolder.Connection;


                txMgrStateObject.ConnectionHolder.TransactionActive = true;

                int timeout = DetermineTimeout(definition);
                if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
                {
                    txMgrStateObject.ConnectionHolder.TimeoutInSeconds = timeout;
                }


                //Bind transactional resources to thread
                if (txMgrStateObject.NewConnectionHolder)
                {
                    TransactionSynchronizationManager.BindResource(DbProvider,
                                                                   txMgrStateObject.ConnectionHolder);
                }
            }
            //TODO catch specific exception
            catch (Exception e)
            {
                ConnectionUtils.DisposeConnection(con, DbProvider);
                throw new CannotCreateTransactionException("Could not create ADO.NET connection for transaction", e);
            }
        }
 /// <summary>The resume.</summary>
 public virtual void Resume()
 {
     if (this.holderActive)
     {
         TransactionSynchronizationManager.BindResource(this.resourceKey, this.resourceHolder);
     }
 }
 /// <summary>
 /// Resume this synchronization.
 /// </summary>
 /// <remarks>
 /// <p>
 /// Supposed to rebind resources from
 /// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager"/>
 /// if managing any.
 /// </p>
 /// </remarks>
 public void Resume()
 {
     if (_holderActive)
     {
         TransactionSynchronizationManager.BindResource(_resourceKey, _resourceHolder);
     }
 }
Esempio n. 7
0
 /// <summary>
 /// Resume this synchronization.
 /// </summary>
 /// <remarks>
 /// <p>
 /// Rebind Hibernate resources from
 /// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager"/>
 /// if managing any.
 /// </p>
 /// </remarks>
 public override void Resume()
 {
     if (this.holderActive)
     {
         TransactionSynchronizationManager.BindResource(this.sessionFactory, this.sessionHolder);
     }
 }
        public void TestTemplateUsesPublisherConnectionUnlessInTx()
        {
            connectionFactory.Destroy();
            template.UsePublisherConnection = true;
            template.ConvertAndSend("dummy", "foo");
            Assert.Null(connectionFactory._connection.Target);
            Assert.NotNull(((CachingConnectionFactory)connectionFactory.PublisherConnectionFactory)._connection.Target);
            connectionFactory.Destroy();
            Assert.Null(connectionFactory._connection.Target);
            Assert.Null(((CachingConnectionFactory)connectionFactory.PublisherConnectionFactory)._connection.Target);
            var channel = connectionFactory.CreateConnection().CreateChannel(true);

            Assert.NotNull(connectionFactory._connection.Target);
            var holder = new RabbitResourceHolder(channel, true);

            TransactionSynchronizationManager.BindResource(connectionFactory, holder);
            try
            {
                template.IsChannelTransacted = true;
                template.ConvertAndSend("dummy", "foo");
                Assert.NotNull(connectionFactory._connection.Target);
                Assert.Null(((CachingConnectionFactory)connectionFactory.PublisherConnectionFactory)._connection.Target);
            }
            finally
            {
                TransactionSynchronizationManager.UnbindResource(connectionFactory);
                channel.Close();
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Open a new session or reconect the
        /// <see cref="IConversationState.RootSessionPerConversation"/> in <paramref name="activeConversation"/>.
        /// Participating in an existing session registed with <see cref="TransactionSynchronizationManager"/>
        /// is not alowed.
        /// </summary>
        /// <param name="activeConversation"></param>
        /// <param name="allManagedConversation"></param>
        /// <exception cref="InvalidOperationException">
        /// <list type="bullet">
        /// <item>If there is another conversation with a <see cref="ISession"/> with opened
        /// <see cref="IDbConnection"/>.</item>
        /// <item>If attempting to participate in an existing NHibernate <see cref="ISessionFactory"/>
        /// managed by <see cref="TransactionSynchronizationManager"/>.
        /// </item>
        /// </list>
        /// </exception>
        public void Open(IConversationState activeConversation, ICollection <IConversationState> allManagedConversation)
        {
            bool isDebugEnabled = log.IsDebugEnabled;

            if (IsOpen)
            {
                if (activeConversation.Id != OpenerConversationId)
                {
                    throw new InvalidOperationException("There is another conversation with a ISession with opened IDbConnection.");
                }
                else
                {
                    if (isDebugEnabled)
                    {
                        log.Debug($"SessionPerConversationScope is already open for this conversation: Id:'{activeConversation.Id}'.");
                    }
                }
            }
            else
            {
                if (activeConversation.SessionFactory != null)
                {
                    if (isDebugEnabled)
                    {
                        log.Debug($"activeConversation with 'session-per-conversation': Id:'{activeConversation.Id}'.");
                    }

                    // single session mode
                    if (TransactionSynchronizationManager.HasResource(activeConversation.SessionFactory))
                    {
                        // Do not modify the Session: just set the participate flag.
                        if (isDebugEnabled)
                        {
                            log.Debug("Participating in existing NHibernate SessionFactory IS NOT ALLOWED.");
                        }
                        throw new InvalidOperationException("Participating in existing NHibernate SessionFactory IS NOT ALLOWED.");
                    }
                    else
                    {
                        if (isDebugEnabled)
                        {
                            log.Debug("Opening single NHibernate Session in SessionPerConversationScope");
                        }

                        TransactionSynchronizationManager.BindResource(activeConversation.SessionFactory, new LazySessionPerConversationHolder(this, activeConversation, allManagedConversation));

                        SetOpen(true);
                        OpenerConversationId = activeConversation.Id;
                    }
                }
                else
                {
                    if (isDebugEnabled)
                    {
                        log.Debug($"activeConversation with NO 'session-per-conversation': Id:'{activeConversation.Id}'.");
                    }
                }
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Get a ADO.NET Connection/Transaction Pair for the given IDbProvider.
        /// Same as <see cref="GetConnection"/> but throwing original provider
        /// exception.
        /// </summary>
        /// <remarks>
        /// Is aware of a corresponding Connection/Transaction bound to the current thread, for example
        /// when using AdoPlatformTransactionManager. Will bind a IDbConnection to the thread
        /// if transaction synchronization is active
        /// </remarks>
        /// <param name="provider">The provider.</param>
        /// <returns></returns>
        public static ConnectionTxPair DoGetConnection(IDbProvider provider)
        {
            AssertUtils.ArgumentNotNull(provider, "provider");
            ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.GetResource(provider);

            if (conHolder != null && (conHolder.HasConnection || conHolder.SynchronizedWithTransaction))
            {
                conHolder.Requested();
                if (!conHolder.HasConnection)
                {
                    if (LOG.IsDebugEnabled)
                    {
                        LOG.Debug("Fetching resumed ADO.NET connection from DbProvider");
                    }
                    conHolder.Connection = provider.CreateConnection();
                }
                return(new ConnectionTxPair(conHolder.Connection, conHolder.Transaction));
            }

            // Else we either got no holder or an empty thread-bound holder here.
            if (LOG.IsDebugEnabled)
            {
                LOG.Debug("Fetching Connection from DbProvider");
            }
            IDbConnection conn = provider.CreateConnection();

            conn.Open();

            if (TransactionSynchronizationManager.SynchronizationActive)
            {
                LOG.Debug("Registering transaction synchronization for IDbConnection");
                //Use same connection for further ADO.NET actions with the transaction.
                //Thread-bound object will get removed by manager at transaction completion.

                ConnectionHolder holderToUse = conHolder;
                if (holderToUse == null)
                {
                    holderToUse = new ConnectionHolder(conn, null);
                }
                else
                {
                    holderToUse.Connection = conn;
                }
                holderToUse.Requested();
                TransactionSynchronizationManager.RegisterSynchronization(
                    new ConnectionSynchronization(holderToUse, provider));
                holderToUse.SynchronizedWithTransaction = true;
                if (holderToUse != conHolder)
                {
                    TransactionSynchronizationManager.BindResource(provider, holderToUse);
                }
            }
            return(new ConnectionTxPair(conn, null));
        }
Esempio n. 11
0
        /// <summary>
        /// Opens a new session or participates in an existing session and
        /// registers with spring's <see cref="TransactionSynchronizationManager"/>.
        /// </summary>
        public void Open()
        {
            if (IsParticipating || IsOpen)
            {
                throw new InvalidOperationException("This scope is already open");
            }

            bool isDebugEnabled = log.IsDebugEnabled;

            if (SingleSession)
            {
                // single session mode
                if (TransactionSynchronizationManager.HasResource(SessionFactory))
                {
                    // Do not modify the Session: just set the participate flag.
                    if (isDebugEnabled)
                    {
                        log.Debug("Participating in existing Hibernate SessionFactory");
                    }
                    SetParticipating(true);
                }
                else
                {
                    if (isDebugEnabled)
                    {
                        log.Debug("Opening single Hibernate Session in SessionScope");
                    }
                    TransactionSynchronizationManager.BindResource(SessionFactory, new LazySessionHolder(this));
                }
            }
            else
            {
                // deferred close mode
                if (SessionFactoryUtils.IsDeferredCloseActive(SessionFactory))
                {
                    // Do not modify deferred close: just set the participate flag.
                    if (isDebugEnabled)
                    {
                        log.Debug("Participating in active deferred close mode");
                    }
                    SetParticipating(true);
                }
                else
                {
                    if (isDebugEnabled)
                    {
                        log.Debug("Initializing deferred close mode");
                    }
                    SessionFactoryUtils.InitDeferredClose(SessionFactory);
                }
            }

            SetOpen(true);
        }
        /// <summary>Bind a resource to a transaction.</summary>
        /// <param name="resourceHolder">The resource holder.</param>
        /// <param name="connectionFactory">The connection factory.</param>
        /// <param name="synched">The synched.</param>
        public static void BindResourceToTransaction(RabbitResourceHolder resourceHolder, IConnectionFactory connectionFactory, bool synched)
        {
            if (TransactionSynchronizationManager.HasResource(connectionFactory) || !TransactionSynchronizationManager.ActualTransactionActive || !synched)
            {
                return;
            }

            TransactionSynchronizationManager.BindResource(connectionFactory, resourceHolder);
            resourceHolder.SynchronizedWithTransaction = true;
            if (TransactionSynchronizationManager.SynchronizationActive)
            {
                TransactionSynchronizationManager.RegisterSynchronization(new RabbitResourceSynchronization(resourceHolder, connectionFactory, synched));
            }
        }
        /// <summary>
        /// Resume the resources of the current transaction.
        /// </summary>
        /// <param name="transaction">
        /// Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.
        /// </param>
        /// <param name="suspendedResources">
        /// The object that holds suspended resources as returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoSuspend"/>.
        /// </param>
        /// <remarks>
        /// Transaction synchronization will be resumed afterwards.
        /// </remarks>
        /// <exception cref="Spring.Transaction.IllegalTransactionStateException">
        /// If suspending is not supported by the transaction manager implementation.
        /// </exception>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of system errors.
        /// </exception>
        protected override void DoResume(Object transaction, Object suspendedResources)
        {
            logger.Debug("Do Resume");
            SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder)suspendedResources;
            Db4oTransactionObject    txObject        = (Db4oTransactionObject)transaction;

            txObject.ObjectContainerHolder = resourcesHolder.ObjectContainerHolder;
            if (TransactionSynchronizationManager.HasResource(_DataSource))
            {
                TransactionSynchronizationManager.UnbindResource(_DataSource);
            }
            TransactionSynchronizationManager.BindResource(_DataSource,
                                                           resourcesHolder.ObjectContainerHolder);
        }
        /// <summary>
        /// Resume the resources of the current transaction.
        /// </summary>
        /// <param name="transaction">
        /// Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.
        /// </param>
        /// <param name="suspendedResources">
        /// The object that holds suspended resources as returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoSuspend"/>.
        /// </param>
        /// <remarks>
        /// Transaction synchronization will be resumed afterwards.
        /// </remarks>
        /// <exception cref="Spring.Transaction.IllegalTransactionStateException">
        /// If suspending is not supported by the transaction manager implementation.
        /// </exception>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of system errors.
        /// </exception>
        protected override void DoResume(object transaction, object suspendedResources)
        {
            SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder)suspendedResources;

            if (TransactionSynchronizationManager.HasResource(SessionFactory))
            {
                // From non-transactional code running in active transaction synchronization
                // -> can be safely removed, will be closed on transaction completion.
                TransactionSynchronizationManager.UnbindResource(SessionFactory);
            }
            TransactionSynchronizationManager.BindResource(SessionFactory, resourcesHolder.SessionHolder);
            if (DbProvider != null)
            {
                TransactionSynchronizationManager.BindResource(DbProvider, resourcesHolder.ConnectionHolder);
            }
        }
Esempio n. 15
0
        public static RabbitResourceHolder BindResourceToTransaction(RabbitResourceHolder resourceHolder, IConnectionFactory connectionFactory, bool synched)
        {
            if (TransactionSynchronizationManager.HasResource(connectionFactory) || !TransactionSynchronizationManager.IsActualTransactionActive() || !synched)
            {
                return((RabbitResourceHolder)TransactionSynchronizationManager.GetResource(connectionFactory)); // NOSONAR never null
            }

            TransactionSynchronizationManager.BindResource(connectionFactory, resourceHolder);
            resourceHolder.SynchronizedWithTransaction = true;
            if (TransactionSynchronizationManager.IsSynchronizationActive())
            {
                TransactionSynchronizationManager.RegisterSynchronization(new RabbitResourceSynchronization(resourceHolder, connectionFactory));
            }

            return(resourceHolder);
        }
        public void TestChannelCloseInTx()
        {
            connectionFactory.IsPublisherReturns = false;
            var channel = connectionFactory.CreateConnection().CreateChannel(true);
            var holder  = new RabbitResourceHolder(channel, true);

            TransactionSynchronizationManager.BindResource(connectionFactory, holder);
            try
            {
                template.IsChannelTransacted = true;
                template.ConvertAndSend(ROUTE, "foo");
                template.ConvertAndSend(Guid.NewGuid().ToString(), ROUTE, "xxx");
                var n = 0;
                while (n++ < 100 && channel.IsOpen)
                {
                    Thread.Sleep(100);
                }

                Assert.False(channel.IsOpen);

                try
                {
                    template.ConvertAndSend(ROUTE, "bar");
                    throw new Exception("Expected exception");
                }
                catch (RabbitUncategorizedException e)
                {
                    if (e.InnerException is InvalidOperationException)
                    {
                        Assert.Contains("Channel closed during transaction", e.InnerException.Message);
                    }
                    else
                    {
                        throw new Exception("Expected InvalidOperationException");
                    }
                }
                catch (RabbitConnectException e)
                {
                    Assert.IsType <R.Exceptions.AlreadyClosedException>(e.InnerException);
                }
            }
            finally
            {
                TransactionSynchronizationManager.UnbindResource(connectionFactory);
                channel.Close();
            }
        }
        /// <summary>Invokes the specified listener</summary>
        /// <param name="channel">The channel to operate on.</param>
        /// <param name="message">The received message.</param>
        /// <see cref="MessageListener"/>
        public virtual void InvokeListener(IModel channel, Message message)
        {
            var listener = this.MessageListener;

            if (listener is IChannelAwareMessageListener)
            {
                this.DoInvokeListener((IChannelAwareMessageListener)listener, channel, message);
            }
            else if (listener is IMessageListener || listener is Action <Message> )
            {
                var bindChannel = this.ExposeListenerChannel && this.IsChannelLocallyTransacted(channel);
                if (bindChannel)
                {
                    var resourceHolder = new RabbitResourceHolder(channel, false);
                    resourceHolder.SynchronizedWithTransaction = true;
                    TransactionSynchronizationManager.BindResource(this.ConnectionFactory, resourceHolder);
                }

                try
                {
                    if (listener is IMessageListener)
                    {
                        this.DoInvokeListener((IMessageListener)listener, message);
                    }
                    else if (listener is Action <Message> )
                    {
                        this.DoInvokeListener((Action <Message>)listener, message);
                    }
                }
                finally
                {
                    if (bindChannel)
                    {
                        // unbind if we bound
                        TransactionSynchronizationManager.UnbindResource(this.ConnectionFactory);
                    }
                }
            }
            else if (listener != null)
            {
                throw new ArgumentException("Only MessageListener and SessionAwareMessageListener supported: " + listener);
            }
            else
            {
                throw new InvalidOperationException("No message listener specified - see property MessageListener");
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Begin a new transaction with the given transaction definition.
        /// </summary>
        /// <param name="transaction">Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
        /// <param name="definition"><see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing
        /// propagation behavior, isolation level, timeout etc.</param>
        /// <remarks>
        /// Does not have to care about applying the propagation behavior,
        /// as this has already been handled by this abstract manager.
        /// </remarks>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of creation or system errors.
        /// </exception>
        protected override void DoBegin(object transaction, ITransactionDefinition definition)
        {
            //This is the default value defined in DefaultTransactionDefinition
            if (definition.TransactionIsolationLevel != IsolationLevel.ReadCommitted)
            {
                throw new InvalidIsolationLevelException("EMS does not support an isoliation level concept");
            }
            EmsTransactionObject txObject = (EmsTransactionObject)transaction;
            IConnection          con      = null;
            ISession             session  = null;

            try
            {
                con     = CreateConnection();
                session = CreateSession(con);
                if (LOG.IsDebugEnabled)
                {
                    log.Debug("Created EMS transaction on Session [" + session + "] from Connection [" + con + "]");
                }
                txObject.ResourceHolder = new EmsResourceHolder(ConnectionFactory, con, session);
                txObject.ResourceHolder.SynchronizedWithTransaction = true;
                int timeout = DetermineTimeout(definition);
                if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
                {
                    txObject.ResourceHolder.TimeoutInSeconds = timeout;
                }
                TransactionSynchronizationManager.BindResource(ConnectionFactory, txObject.ResourceHolder);
            } catch (EMSException ex)
            {
                if (session != null)
                {
                    try
                    {
                        session.Close();
                    } catch (Exception)
                    {}
                }
                if (con != null)
                {
                    try
                    {
                        con.Close();
                    } catch (Exception) {}
                }
                throw new CannotCreateTransactionException("Could not create EMS Transaction", ex);
            }
        }
Esempio n. 19
0
        /// <summary>The do get transaction.</summary>
        /// <returns>The System.Object.</returns>
        protected override object DoGetTransaction()
        {
            var            transaction = new ResourcelessTransaction();
            Stack <object> resources;

            if (!TransactionSynchronizationManager.HasResource(this))
            {
                resources = new Stack <object>();
                TransactionSynchronizationManager.BindResource(this, resources);
            }
            else
            {
                var stack = (Stack <object>)TransactionSynchronizationManager.GetResource(this);
                resources = stack;
            }

            resources.Push(transaction);
            return(transaction);
        }
        /// <summary>
        /// Begin a new transaction with the given transaction definition.
        /// </summary>
        /// <param name="transaction">Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
        /// <param name="definition"><see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing
        /// propagation behavior, isolation level, timeout etc.</param>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of creation or system errors.
        /// </exception>
        protected override void DoBegin(object transaction, ITransactionDefinition definition)
        {
            MessageQueueTransactionObject txObject = (MessageQueueTransactionObject)transaction;

            MessageQueueTransaction mqt = new MessageQueueTransaction();

            mqt.Begin();

            txObject.ResourceHolder = new MessageQueueResourceHolder(mqt);
            txObject.ResourceHolder.SynchronizedWithTransaction = true;

            int timeout = DetermineTimeout(definition);

            if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
            {
                txObject.ResourceHolder.TimeoutInSeconds = timeout;
            }
            TransactionSynchronizationManager.BindResource(CURRENT_TRANSACTION_SLOTNAME, txObject.ResourceHolder);
        }
 public void OnMessage(Message message)
 {
     bool exposeResource = container.ExposeListenerSession;
     if (exposeResource)
     {
         TransactionSynchronizationManager.BindResource(
             container.ConnectionFactory, new LocallyExposedEmsResourceHolder(session));
     }
     try
     {
         container.ExecuteListener(session, message);
     } finally
     {
         if (exposeResource)
         {
             TransactionSynchronizationManager.UnbindResource(container.ConnectionFactory);
         }
     }
 }
Esempio n. 22
0
        /// <summary>
        /// Method DoGetConnection does the actual Connection creation/recuperation
        /// It throws the orgiginal DB4o Exceptions
        /// </summary>
        /// <param name="dataSource">An IDb4oDataSource</param>
        /// <returns>An ObjectContainer</retutns>
        private static ObjectContainer DoGetConnection(IDb4oDataSource dataSource)
        {
            logger.Debug("Do Get Connection");
            logger.Debug("GetResource from TransactionSynchronizationManager");
            ObjectContainerHolder holder = (ObjectContainerHolder )TransactionSynchronizationManager.GetResource(dataSource);

            ObjectContainer container;

            if (holder != null)
            {
                logger.Debug("ObjectContainerHolder exists");
                holder.Requested();
                if (holder.ObjectContainer == null)
                {
                    logger.Debug("No connection inside the ObjectContainerHolder");
                    logger.Debug("Creating One");
                    holder.ObjectContainer = dataSource.GetConnection();
                }
                container = holder.ObjectContainer;
            }
            else
            {
                // the connection should be created
                logger.Debug("The Holder does not exist. It will be created");
                container = dataSource.GetConnection();
                if (TransactionSynchronizationManager.SynchronizationActive)
                {
                    logger.Debug("Registerbe increaseing transaction synchronization");
                    logger.Debug("Will use the same connection for further DB4o actions within the transaction");
                    logger.Debug("Thread-bound object will get removed by synchronization at transaction completion");
                    holder = new ObjectContainerHolder(container);
                    holder.SynchronizedWithTransaction = true;
                    holder.Requested();
                    TransactionSynchronizationManager.RegisterSynchronization(
                        new ObjectContainerSynchronization(holder, dataSource));
                    TransactionSynchronizationManager.BindResource(dataSource, holder);
                }
            }

            return(container);
        }
Esempio n. 23
0
        /// <summary>
        /// 事务开始
        /// </summary>
        protected void BeginTransaction(IDbProvider dbProvider, IUnitOfWorkDefinition definition)
        {
            CheckUnitOfWorkOutMostFlag(dbProvider);

            //从当前线程中获取
            ConnectionHolder conHolder = GetConnectionHolder(dbProvider);

            //如果当前线程中存在ConnectionHolder,则此事务为嵌套事务,外层事务已存在多年;
            if (conHolder != null)
            {
                Logger.Debug(m => m("[AbstractUnitOfWork.BeginTransaction]:Inner(deepth:{0}) unit of work initiates with definition({1})!",
                                    UnitOfWorkStackManager.Count, definition));
            }
            else             //外层事务
            {
                Logger.Debug(m => m("[AbstractUnitOfWork.BeginTransaction]:Outer most unit of work initiates with definition({0})!", definition));
                ConnectionHolder connectionHolder = CreateConnectionHolder();
                TransactionSynchronizationManager.BindResource(dbProvider, connectionHolder);
                Logger.Debug(m => m("[AbstractUnitOfWork.BeginTransaction]:UnitOfWork created with(connstring:{0})", connectionHolder.Connection.ConnectionString));
            }
        }
Esempio n. 24
0
        /// <summary>Do begin.</summary>
        /// <param name="transaction">The transaction.</param>
        /// <param name="definition">The definition.</param>
        protected override void DoBegin(object transaction, ITransactionDefinition definition)
        {
            // https://jira.springsource.org/browse/SPRNET-1444 (SPRNET 2.0) has default TransactionIsolationLevel as IsolationLevel.Unspecified, letting this work. Will not work for SPRNET <= 1.3.2.
            if (definition.TransactionIsolationLevel != IsolationLevel.Unspecified)
            {
                throw new InvalidIsolationLevelException("AMQP does not support an isolation level concept");
            }

            var transactionObject = (RabbitTransactionObject)transaction;
            RabbitResourceHolder resourceHolder = null;

            try
            {
                resourceHolder = ConnectionFactoryUtils.GetTransactionalResourceHolder(this.ConnectionFactory, true);
                Logger.Debug(m => m("Created AMQP transaction on channel [{0}]", resourceHolder.Channel));

                // resourceHolder.DeclareTransactional();
                transactionObject.ResourceHolder = resourceHolder;
                transactionObject.ResourceHolder.SynchronizedWithTransaction = true;
                var timeout = this.DetermineTimeout(definition);
                if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
                {
                    transactionObject.ResourceHolder.TimeoutInSeconds = timeout;
                }

                TransactionSynchronizationManager.BindResource(this.ConnectionFactory, transactionObject.ResourceHolder);
            }
            catch (AmqpException ex)
            {
                if (resourceHolder != null)
                {
                    ConnectionFactoryUtils.ReleaseResources(resourceHolder);
                }

                throw new CannotCreateTransactionException("Could not create AMQP transaction", ex);
            }
        }
Esempio n. 25
0
        protected virtual void ActualInvokeListener(R.IModel channel, object data)
        {
            var listener = MessageListener;

            if (listener is IChannelAwareMessageListener chanListener)
            {
                DoInvokeListener(chanListener, channel, data);
            }
            else if (listener != null)
            {
                var bindChannel = ExposeListenerChannel && IsChannelLocallyTransacted;
                if (bindChannel)
                {
                    var resourceHolder = new RabbitResourceHolder(channel, false, _logger);
                    resourceHolder.SynchronizedWithTransaction = true;
                    TransactionSynchronizationManager.BindResource(ConnectionFactory, resourceHolder);
                }

                try
                {
                    DoInvokeListener(listener, data);
                }
                finally
                {
                    if (bindChannel)
                    {
                        // unbind if we bound
                        TransactionSynchronizationManager.UnbindResource(ConnectionFactory);
                    }
                }
            }
            else
            {
                throw new FatalListenerExecutionException("No message listener specified - see property 'messageListener'");
            }
        }
        /// <summary>
        /// Does the recieve and execute using a local MessageQueueTransaction.
        /// </summary>
        /// <param name="mq">The mqessage queue.</param>
        /// <param name="status">The transactional status.</param>
        /// <returns>true if should continue peeking, false otherwise.</returns>
        protected virtual bool DoRecieveAndExecuteUsingResourceTransactionManagerWithTxQueue(MessageQueue mq,
                                                                                             ITransactionStatus status)
        {
            #region Logging

            if (LOG.IsDebugEnabled)
            {
                LOG.Debug("Executing DoRecieveAndExecuteUsingResourceTransactionManagerWithTxQueue");
            }

            #endregion Logging

            using (MessageQueueTransaction messageQueueTransaction = new MessageQueueTransaction())
            {
                messageQueueTransaction.Begin();

                #region Logging

                if (LOG.IsTraceEnabled)
                {
                    LOG.Trace("Started MessageQueueTransaction for queue = [" + mq.Path + "]");
                }

                #endregion

                Message message;

                #region ReceiveMessage

                try
                {
                    #region Logging

                    if (LOG.IsTraceEnabled)
                    {
                        LOG.Trace("Receiving message with zero timeout for queue = [" + mq.Path + "]");
                    }

                    #endregion

                    message = mq.Receive(TimeSpan.Zero, messageQueueTransaction);
                }
                catch (MessageQueueException ex)
                {
                    if (ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
                    {
                        //expected to occur occasionally

                        #region Logging

                        if (LOG.IsTraceEnabled)
                        {
                            LOG.Trace(
                                "MessageQueueErrorCode.IOTimeout: No message available to receive.  May have been processed by another thread.");
                        }

                        #endregion

                        status.SetRollbackOnly();
                        return(false); // no more peeking unless this is the last listener thread
                    }
                    else
                    {
                        // A real issue in receiving the message

                        #region Logging

                        if (LOG.IsErrorEnabled)
                        {
                            LOG.Error("Error receiving message from DefaultMessageQueue [" + mq.Path +
                                      "], closing queue and clearing connection cache.");
                        }

                        #endregion

                        lock (messageQueueMonitor)
                        {
                            mq.Close();
                            MessageQueue.ClearConnectionCache();
                        }
                        throw; // will cause rollback in surrounding platform transaction manager and log exception
                    }
                }

                #endregion

                if (message == null)
                {
                    #region Logging

                    if (LOG.IsTraceEnabled)
                    {
                        LOG.Trace("Message recieved is null from Queue = [" + mq.Path + "]");
                    }

                    #endregion

                    status.SetRollbackOnly();
                    return(false); // no more peeking unless this is the last listener thread
                }

                try
                {
                    #region Logging

                    if (LOG.IsDebugEnabled)
                    {
                        LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.Path + "]");
                    }

                    #endregion

                    MessageReceived(message);

                    if (ExposeContainerManagedMessageQueueTransaction)
                    {
                        TransactionSynchronizationManager.BindResource(
                            MessageQueueTransactionManager.CURRENT_TRANSACTION_SLOTNAME,
                            new LocallyExposedMessageQueueResourceHolder(messageQueueTransaction));
                    }

                    DoExecuteListener(message);

                    #region Logging

                    if (LOG.IsTraceEnabled)
                    {
                        LOG.Trace("MessageListener executed");
                    }

                    #endregion

                    messageQueueTransaction.Commit();

                    #region Logging

                    if (LOG.IsTraceEnabled)
                    {
                        LOG.Trace("Committed MessageQueueTransaction for queue [" + mq.Path + "]");
                    }

                    #endregion
                }
                catch (Exception ex)
                {
                    TransactionAction action =
                        HandleTransactionalListenerException(ex, message, messageQueueTransaction);
                    if (action == TransactionAction.Rollback)
                    {
                        messageQueueTransaction.Abort();

                        #region Logging

                        if (LOG.IsDebugEnabled)
                        {
                            LOG.Debug(
                                "Exception handler's TransactionAction has rolled back MessageQueueTransaction for queue [" +
                                mq.Path + "]");
                        }

                        #endregion
                    }
                    else
                    {
                        // Will remove from the message queue
                        messageQueueTransaction.Commit();

                        #region Logging

                        if (LOG.IsDebugEnabled)
                        {
                            LOG.Debug(
                                "Exception handler's TransactionAction has committed MessageQueueTransaction for queue [" +
                                mq.Path + "]");
                        }

                        #endregion
                    }
                    //Outer db-tx will rollback
                    throw;
                }
                finally
                {
                    if (ExposeContainerManagedMessageQueueTransaction)
                    {
                        TransactionSynchronizationManager.UnbindResource(
                            MessageQueueTransactionManager.CURRENT_TRANSACTION_SLOTNAME);
                    }
                    message.Dispose();
                }
                return(true);
            }
        }
        /// <summary>
        /// Begin a new transaction with the given transaction definition.
        /// </summary>
        /// <param name="transaction">
        /// Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.
        /// </param>
        /// <param name="definition">
        /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing
        /// propagation behavior, isolation level, timeout etc.
        /// </param>
        /// <remarks>
        /// Does not have to care about applying the propagation behavior,
        /// as this has already been handled by this abstract manager.
        /// </remarks>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of creation or system errors.
        /// </exception>
        protected override void DoBegin(object transaction, ITransactionDefinition definition)
        {
            TxScopeTransactionManager.PromotableTxScopeTransactionObject promotableTxScopeTransactionObject =
                ((HibernateTransactionObject)transaction).PromotableTxScopeTransactionObject;
            try
            {
                DoTxScopeBegin(promotableTxScopeTransactionObject, definition);
            }
            catch (Exception e)
            {
                throw new CannotCreateTransactionException("Transaction Scope failure on begin", e);
            }

            HibernateTransactionObject txObject = (HibernateTransactionObject)transaction;

            if (DbProvider != null && TransactionSynchronizationManager.HasResource(DbProvider) &&
                !txObject.ConnectionHolder.SynchronizedWithTransaction)
            {
                throw new IllegalTransactionStateException(
                          "Pre-bound ADO.NET Connection found - HibernateTransactionManager does not support " +
                          "running within AdoTransactionManager if told to manage the DbProvider itself. " +
                          "It is recommended to use a single HibernateTransactionManager for all transactions " +
                          "on a single DbProvider, no matter whether Hibernate or ADO.NET access.");
            }
            ISession session = null;

            try
            {
                if (txObject.SessionHolder == null || txObject.SessionHolder.SynchronizedWithTransaction)
                {
                    IInterceptor interceptor = EntityInterceptor;
                    ISession     newSession  = (interceptor != null ?
                                                SessionFactory.OpenSession(interceptor) : SessionFactory.OpenSession());

                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Opened new Session [" + newSession + "] for Hibernate transaction");
                    }
                    txObject.SetSessionHolder(new SessionHolder(newSession), true);
                }
                txObject.SessionHolder.SynchronizedWithTransaction = true;
                session = txObject.SessionHolder.Session;

                IDbConnection con = session.Connection;
                //TODO isolation level mgmt
                //IsolationLevel previousIsolationLevel =

                if (definition.ReadOnly && txObject.NewSessionHolder)
                {
                    // Just set to NEVER in case of a new Session for this transaction.
                    session.FlushMode = FlushMode.Never;
                }

                if (!definition.ReadOnly && !txObject.NewSessionHolder)
                {
                    // We need AUTO or COMMIT for a non-read-only transaction.
                    FlushMode flushMode = session.FlushMode;
                    if (FlushMode.Never == flushMode)
                    {
                        session.FlushMode = FlushMode.Auto;
                        txObject.SessionHolder.PreviousFlushMode = flushMode;
                    }
                }

                // Add the Hibernate transaction to the session holder.
                // for now pass in tx options isolation level.
                ITransaction   hibernateTx = session.BeginTransaction(definition.TransactionIsolationLevel);
                IDbTransaction adoTx       = GetIDbTransaction(hibernateTx);

                // Add the Hibernate transaction to the session holder.
                txObject.SessionHolder.Transaction = hibernateTx;

                // Register transaction timeout.
                int timeout = DetermineTimeout(definition);
                if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
                {
                    txObject.SessionHolder.TimeoutInSeconds = timeout;
                }

                // Register the Hibernate Session's ADO.NET Connection/TX pair for the DbProvider, if set.
                if (DbProvider != null)
                {
                    //investigate passing null for tx.
                    ConnectionHolder conHolder = new ConnectionHolder(con, adoTx);
                    if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
                    {
                        conHolder.TimeoutInMillis = definition.TransactionTimeout;
                    }
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Exposing Hibernate transaction as ADO transaction [" + con + "]");
                    }
                    TransactionSynchronizationManager.BindResource(DbProvider, conHolder);
                    txObject.ConnectionHolder = conHolder;
                }

                // Bind the session holder to the thread.
                if (txObject.NewSessionHolder)
                {
                    TransactionSynchronizationManager.BindResource(SessionFactory, txObject.SessionHolder);
                }
            }
            catch (Exception ex)
            {
                SessionFactoryUtils.CloseSession(session);
                throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex);
            }
        }
Esempio n. 28
0
        /// <summary>
        /// Resume the resources of the current transaction.
        /// </summary>
        /// <param name="transaction">Transaction object returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
        /// <param name="suspendedResources">The object that holds suspended resources as returned by
        /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoSuspend"/>.</param>
        /// <remarks>Transaction synchronization will be resumed afterwards.
        /// </remarks>
        /// <exception cref="Spring.Transaction.TransactionException">
        /// In the case of system errors.
        /// </exception>
        protected override void DoResume(object transaction, object suspendedResources)
        {
            EmsResourceHolder conHolder = (EmsResourceHolder)suspendedResources;

            TransactionSynchronizationManager.BindResource(ConnectionFactory, conHolder);
        }
        private static ISession DoGetSession(
            ISessionFactory sessionFactory, IInterceptor entityInterceptor,
            IAdoExceptionTranslator adoExceptionTranslator, bool allowCreate)
        {
            AssertUtils.ArgumentNotNull(sessionFactory, "sessionFactory", "SessionFactory can not be null");

            SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.GetResource(sessionFactory);

            if (sessionHolder != null && !sessionHolder.IsEmpty)
            {
                // pre-bound Hibernate Session
                ISession session = null;
                if (TransactionSynchronizationManager.SynchronizationActive &&
                    sessionHolder.DoesNotHoldNonDefaultSession)
                {
                    // Spring transaction management is active ->
                    // register pre-bound Session with it for transactional flushing.
                    session = sessionHolder.ValidatedSession;
                    if (!sessionHolder.SynchronizedWithTransaction)
                    {
                        log.Debug("Registering Spring transaction synchronization for existing Hibernate Session");
                        TransactionSynchronizationManager.RegisterSynchronization(
                            new SpringSessionSynchronization(sessionHolder, sessionFactory, adoExceptionTranslator, false));
                        sessionHolder.SynchronizedWithTransaction = true;
                        // Switch to FlushMode.AUTO if we're not within a read-only transaction.
                        FlushMode flushMode = session.FlushMode;
                        if (FlushMode.Never == flushMode &&
                            !TransactionSynchronizationManager.CurrentTransactionReadOnly)
                        {
                            session.FlushMode = FlushMode.Auto;
                            sessionHolder.PreviousFlushMode = flushMode;
                        }
                    }
                }
                else
                {
                    // No Spring transaction management active -> simply return default thread-bound Session, if any
                    // (possibly from OpenSessionInViewModule)
                    session = sessionHolder.ValidatedSession;
                }

                if (session != null)
                {
                    return(session);
                }
            }


            ISession sess = OpenSession(sessionFactory, entityInterceptor);

            // Set Session to FlushMode.Never if we're within a read-only transaction.
            // Use same Session for further Hibernate actions within the transaction.
            // Thread object will get removed by synchronization at transaction completion.
            if (TransactionSynchronizationManager.SynchronizationActive)
            {
                log.Debug("Registering Spring transaction synchronization for new Hibernate Session");
                SessionHolder holderToUse = sessionHolder;
                if (holderToUse == null)
                {
                    holderToUse = new SessionHolder(sess);
                }
                else
                {
                    holderToUse.AddSession(sess);
                }
                if (TransactionSynchronizationManager.CurrentTransactionReadOnly)
                {
                    sess.FlushMode = FlushMode.Never;
                }
                TransactionSynchronizationManager.RegisterSynchronization(
                    new SpringSessionSynchronization(holderToUse, sessionFactory, adoExceptionTranslator, true));
                holderToUse.SynchronizedWithTransaction = true;
                if (holderToUse != sessionHolder)
                {
                    TransactionSynchronizationManager.BindResource(sessionFactory, holderToUse);
                }
            }



            // Check whether we are allowed to return the Session.
            if (!allowCreate && !IsSessionTransactional(sess, sessionFactory))
            {
                CloseSession(sess);
                throw new InvalidOperationException("No Hibernate Session bound to thread, " +
                                                    "and configuration does not allow creation of non-transactional one here");
            }

            return(sess);
        }
        private static MongoDatabase DoGetDatabase(MongoServer mongo, string databaseName, MongoCredentials credentials,
                                                   WriteConcern writeConcern, bool allowCreate)
        {
            var dbHolder = (DatabaseHolder)TransactionSynchronizationManager.GetResource(mongo);

            // Do we have a populated holder and TX sync active?
            if (dbHolder != null && !dbHolder.IsEmpty && TransactionSynchronizationManager.SynchronizationActive)
            {
                var holderDatabase = dbHolder.GetDatabase(databaseName);

                // DB found but not yet synchronized
                if (holderDatabase != null && !dbHolder.SynchronizedWithTransaction)
                {
                    Log.Debug(
                        m => m("Registering Spring transaction synchronization for existing MongoDB {0}.", databaseName));

                    TransactionSynchronizationManager.RegisterSynchronization(new MongoSynchronization(dbHolder, mongo));
                    dbHolder.SynchronizedWithTransaction = true;
                }

                if (holderDatabase != null)
                {
                    return(holderDatabase);
                }
            }

            // Lookup fresh database instance
            Log.Debug(m => m("Getting Mongo Database name=[{0}]", databaseName));

            if (writeConcern == null)
            {
                writeConcern = WriteConcern.Acknowledged;
            }

            var newDatabase = credentials != null
                                  ? mongo.GetDatabase(databaseName, credentials, writeConcern)
                                  : mongo.GetDatabase(databaseName, writeConcern);

            // TX sync active, bind new database to thread
            if (TransactionSynchronizationManager.SynchronizationActive)
            {
                Log.Debug(
                    m => m("Registering Spring transaction synchronization for MongoDB instance {0}.", databaseName));

                DatabaseHolder holderToUse = dbHolder;

                if (holderToUse == null)
                {
                    holderToUse = new DatabaseHolder(databaseName, newDatabase);
                }
                else
                {
                    holderToUse.AddDatabase(databaseName, newDatabase);
                }

                TransactionSynchronizationManager.RegisterSynchronization(new MongoSynchronization(holderToUse, mongo));
                holderToUse.SynchronizedWithTransaction = true;

                if (holderToUse != dbHolder)
                {
                    TransactionSynchronizationManager.BindResource(mongo, holderToUse);
                }
            }

            // Check whether we are allowed to return the DB.
            if (!allowCreate && !IsDbTransactional(newDatabase, mongo))
            {
                throw new InvalidOperationException("No Mongo DB bound to thread, "
                                                    +
                                                    "and configuration does not allow creation of non-transactional one here");
            }

            return(newDatabase);
        }