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); } }
/// <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); } }
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); } }
/// <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(); } }
/// <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}'."); } } } }
/// <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)); }
/// <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); } }
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"); } }
/// <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); } }
/// <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); } } }
/// <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); }
/// <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)); } }
/// <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); } }
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); } }
/// <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); }