Inheritance: BaseDataStructure
Esempio n. 1
0
		public TransactionState this[TransactionId id]
		{
			get
			{
				TransactionState state;

				if(transactions.TryGetValue(id, out state))
				{
					return state;
				}

				return null;
			}
		}
Esempio n. 2
0
		public TransactionState(TransactionId id)
		{
			this.id = id;
		}
 /// <summary>
 /// Converts the given transaction ID into a String
 /// </summary>
 public static String ToString(TransactionId txnId)
 {
     if (txnId is LocalTransactionId)
     {
         LocalTransactionId ltxnId = (LocalTransactionId) txnId;
         return "" + ltxnId.Value;
     }
     else if (txnId is XATransactionId)
     {
         XATransactionId xaTxnId = (XATransactionId) txnId;
         return "XID:" + xaTxnId.FormatId + ":" + ToHexFromBytes(xaTxnId.GlobalTransactionId) + ":" + ToHexFromBytes(xaTxnId.BranchQualifier);
     }
     return null;
 }
Esempio n. 4
0
 public TransactionState removeTransactionState(TransactionId id)
 {
     TransactionState ret = transactions[id];
     transactions.Remove(id);
     return ret;
 }
Esempio n. 5
0
 public void addTransactionState(TransactionId id)
 {
     checkShutdown();
     transactions.Add(id, new TransactionState(id));
 }
Esempio n. 6
0
 public TransactionState this[TransactionId id]
 {
     get
     {
         return transactions[id];
     }
 }
 public virtual bool Equals(TransactionId that)
 {
     return(true);
 }
Esempio n. 8
0
        public void Begin()
        {
            if(!InTransaction)
            {
                this.transactionId = this.session.Connection.CreateLocalTransactionId();
                
                TransactionInfo info = new TransactionInfo();
                info.ConnectionId = this.session.Connection.ConnectionId;
                info.TransactionId = transactionId;
                info.Type = (int) TransactionType.Begin;
                
                this.session.Connection.Oneway(info);

                if(Tracer.IsDebugEnabled)
                {
                    Tracer.Debug("Begin:" + this.transactionId.ToString());
                }
            }
        }
Esempio n. 9
0
		public TransactionState removeTransactionState(TransactionId id)
		{
			TransactionState ret = null;

			transactions.TryGetValue(id, out ret);
			transactions.Remove(id);
			return ret;
		}
Esempio n. 10
0
        public void InDoubt(Enlistment enlistment)
        {
            lock (syncObject)
            {
                try
                {
                    Tracer.Debug("In Doubt notification received for TX id: " + this.transactionId);

                    BeforeEnd();

                    // Now notify the broker that Rollback should be performed.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId = this.connection.ConnectionId;
                    info.TransactionId = this.transactionId;
                    info.Type = (int) TransactionType.End;

                    this.connection.CheckConnected();
                    this.connection.SyncRequest(info);

                    info.Type = (int) TransactionType.Rollback;
                    this.connection.CheckConnected();
                    this.connection.SyncRequest(info);

                    Tracer.Debug("InDoubt Transaction Rollback Done TX id: " + this.transactionId);

                    RecoveryLogger.LogRecovered(this.transactionId as XATransactionId);

                    // if server responds that nothing needs to be done, then reply done.
                    enlistment.Done();

                    AfterRollback();
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.transactionId = null;
                    this.netTxState = TxState.None;

                    CountDownLatch latch = this.recoveryComplete;
                    if (latch != null)
                    {
                        latch.countDown();
                    }

                    this.dtcControlEvent.Set();
                }
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Should be called from NetTxSession when created to check if any TX
        /// data is stored for recovery and whether the Broker has matching info
        /// stored.  If an Transaction is found that belongs to this client and is
        /// still alive on the Broker it will be recovered, otherwise the stored 
        /// data should be cleared.
        /// </summary>
        public void InitializeDtcTxContext()
        {
            // initialize the logger with the current Resource Manager Id
            RecoveryLogger.Initialize(ResourceManagerId);

            KeyValuePair<XATransactionId, byte[]>[] localRecoverables = RecoveryLogger.GetRecoverables();
            if (localRecoverables.Length == 0)
            {
                Tracer.Debug("Did not detect any open DTC transaction records on disk.");
                // No local data so anything stored on the broker can't be recovered here.
                return;
            }

            XATransactionId[] recoverables = TryRecoverBrokerTXIds();
            if (recoverables.Length == 0)
            {
                Tracer.Debug("Did not detect any recoverable transactions at Broker.");
                // Broker has no recoverable data so nothing to do here, delete the 
                // old recovery log as its stale.
                RecoveryLogger.Purge();
                return;
            }

            List<KeyValuePair<XATransactionId, byte[]>> matches = new List<KeyValuePair<XATransactionId, byte[]>>();

            foreach(XATransactionId recoverable in recoverables)
            {
                foreach(KeyValuePair<XATransactionId, byte[]> entry in localRecoverables)
                {
                    if(entry.Key.Equals(recoverable))
                    {
                        Tracer.DebugFormat("Found a matching TX on Broker to stored Id: {0} reenlisting.", entry.Key);
                        matches.Add(entry);
                    }
                }
            }

            if (matches.Count != 0)
            {
                this.recoveryComplete = new CountDownLatch(matches.Count);

                foreach (KeyValuePair<XATransactionId, byte[]> recoverable in matches)
                {
                    this.transactionId = recoverable.Key;
                    Tracer.Info("Reenlisting recovered TX with Id: " + this.transactionId);
                    this.currentEnlistment = 
                        TransactionManager.Reenlist(ResourceManagerGuid, recoverable.Value, this);
                }

                this.recoveryComplete.await();
                Tracer.Debug("All Recovered TX enlistments Reports complete, Recovery Complete.");
                TransactionManager.RecoveryComplete(ResourceManagerGuid);
                return;
            }

            // The old recovery information doesn't match what's on the broker so we
            // should discard it as its stale now.
            RecoveryLogger.Purge();
        }
Esempio n. 12
0
        public void Rollback(Enlistment enlistment)
        {
            lock (this.syncObject)
            {
                try
                {
                    Tracer.Debug("Rollback notification received for TX id: " + this.transactionId);

                    if (this.transactionId != null)
                    {
                        BeforeEnd();

                        // Now notify the broker that a new XA'ish transaction has started.
                        TransactionInfo info = new TransactionInfo();
                        info.ConnectionId = this.connection.ConnectionId;
                        info.TransactionId = this.transactionId;
                        info.Type = (int) TransactionType.End;

                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        info.Type = (int) TransactionType.Rollback;
                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        Tracer.Debug("Transaction Rollback Done TX id: " + this.transactionId);

                        RecoveryLogger.LogRecovered(this.transactionId as XATransactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        enlistment.Done();

                        AfterRollback();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Rollback failed with error: {1}",
                                       this.transactionId, ex.Message);
                    AfterRollback();
                    try
                    {
                        this.connection.OnException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.transactionId = null;
                    this.netTxState = TxState.None;

                    CountDownLatch latch = this.recoveryComplete;
                    if (latch != null)
                    {
                        latch.countDown();
                    }

                    this.dtcControlEvent.Set();
                }
            }
        }
Esempio n. 13
0
        public void SinglePhaseCommit(SinglePhaseEnlistment enlistment)
        {
            lock (this.syncObject)
            {
                try
                {
                    Tracer.Debug("Single Phase Commit notification received for TX id: " + this.transactionId);

                    if (this.transactionId != null)
                    {
                        BeforeEnd();

                        // Now notify the broker that a new XA'ish transaction has completed.
                        TransactionInfo info = new TransactionInfo();
                        info.ConnectionId = this.connection.ConnectionId;
                        info.TransactionId = this.transactionId;
                        info.Type = (int) TransactionType.CommitOnePhase;

                        this.connection.CheckConnected();
                        this.connection.SyncRequest(info);

                        Tracer.Debug("Transaction Single Phase Commit Done TX id: " + this.transactionId);

                        // if server responds that nothing needs to be done, then reply done.
                        enlistment.Done();

                        AfterCommit();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Single Phase Commit failed with error: {1}",
                                       this.transactionId, ex.Message);
                    AfterRollback();
                    enlistment.Done();
                    try
                    {
                        this.connection.OnException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }
                }
                finally
                {
                    this.currentEnlistment = null;
                    this.transactionId = null;
                    this.netTxState = TxState.None;

                    this.dtcControlEvent.Set();
                }
            }
        }
Esempio n. 14
0
        public void Prepare(PreparingEnlistment preparingEnlistment)
        {
            lock (this.syncObject)
            {
                this.netTxState = TxState.Pending;

                try
                {
                    Tracer.Debug("Prepare notification received for TX id: " + this.transactionId);

                    BeforeEnd();

                    // Before sending the request to the broker, log the recovery bits, if
                    // this fails we can't prepare and the TX should be rolled back.
                    RecoveryLogger.LogRecoveryInfo(this.transactionId as XATransactionId,
                                                   preparingEnlistment.RecoveryInformation());

                    // Inform the broker that work on the XA'sh TX Branch is complete.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId = this.connection.ConnectionId;
                    info.TransactionId = this.transactionId;
                    info.Type = (int) TransactionType.End;

                    this.connection.CheckConnected();
                    this.connection.SyncRequest(info);

                    // Prepare the Transaction for commit.
                    info.Type = (int) TransactionType.Prepare;
                    IntegerResponse response = (IntegerResponse) this.connection.SyncRequest(info);
                    if (response.Result == XA_READONLY)
                    {
                        Tracer.Debug("Transaction Prepare done and doesn't need a commit, TX id: " + this.transactionId);

                        this.transactionId = null;
                        this.currentEnlistment = null;

                        // Read Only means there's nothing to recover because there was no
                        // change on the broker.
                        RecoveryLogger.LogRecovered(this.transactionId as XATransactionId);

                        // if server responds that nothing needs to be done, then reply prepared
                        // but clear the current state data so we appear done to the commit method.
                        preparingEnlistment.Prepared();

                        // Done so commit won't be called.
                        AfterCommit();

                        // A Read-Only TX is considered closed at this point, DTC won't call us again.
                        this.dtcControlEvent.Set();
                    }
                    else
                    {
                        Tracer.Debug("Transaction Prepare succeeded TX id: " + this.transactionId);

                        // If work finished correctly, reply prepared
                        preparingEnlistment.Prepared();
                    }
                }
                catch (Exception ex)
                {
                    Tracer.DebugFormat("Transaction[{0}] Prepare failed with error: {1}",
                                       this.transactionId, ex.Message);

                    AfterRollback();
                    preparingEnlistment.ForceRollback();
                    try
                    {
                        this.connection.OnException(ex);
                    }
                    catch (Exception error)
                    {
                        Tracer.Error(error.ToString());
                    }

                    this.currentEnlistment = null;
                    this.transactionId = null;
                    this.netTxState = TxState.None;
                    this.dtcControlEvent.Set();
                }
            }
        }
Esempio n. 15
0
        public void Begin(Transaction transaction)
        {
            lock (syncObject)
            {
                this.netTxState = TxState.Active;
                dtcControlEvent.Reset();

                Tracer.Debug("Begin notification received");

                if (InNetTransaction)
                {
                    throw new TransactionInProgressException("A Transaction is already in Progress");
                }

                try
                {
                    Guid rmId = ResourceManagerGuid;

                    // Enlist this object in the transaction.
                    this.currentEnlistment =
                        transaction.EnlistDurable(rmId, this, EnlistmentOptions.None);

                    Tracer.Debug("Enlisted in Durable Transaction with RM Id: " + rmId);

                    TransactionInformation txInfo = transaction.TransactionInformation;

                    XATransactionId xaId = new XATransactionId();
                    this.transactionId = xaId;

                    if (txInfo.DistributedIdentifier != Guid.Empty)
                    {
                        xaId.GlobalTransactionId = txInfo.DistributedIdentifier.ToByteArray();
                        xaId.BranchQualifier = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
                    }
                    else
                    {
                        xaId.GlobalTransactionId = Encoding.UTF8.GetBytes(txInfo.LocalIdentifier);
                        xaId.BranchQualifier = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString());
                    }

                    // Now notify the broker that a new XA'ish transaction has started.
                    TransactionInfo info = new TransactionInfo();
                    info.ConnectionId = this.connection.ConnectionId;
                    info.TransactionId = this.transactionId;
                    info.Type = (int) TransactionType.Begin;

                    this.session.Connection.Oneway(info);

                    if (Tracer.IsDebugEnabled)
                    {
                        Tracer.Debug("Began XA'ish Transaction:" + xaId.GlobalTransactionId.ToString());
                    }
                }
                catch (Exception)
                {
                    dtcControlEvent.Set();
                    throw;
                }
            }
        }
Esempio n. 16
0
     public void Commit()
     {
         if(InTransaction)
         {
             this.BeforeEnd();
 
             if(Tracer.IsDebugEnabled)
             {
                 Tracer.Debug("Commit: "  + this.transactionId +
                              " syncCount: " +
                              (synchronizations != null ? synchronizations.Count : 0));
             }
 
             TransactionInfo info = new TransactionInfo();
             info.ConnectionId = this.session.Connection.ConnectionId;
             info.TransactionId = transactionId;
             info.Type = (int) TransactionType.CommitOnePhase;
             
             this.transactionId = null;
             this.session.Connection.SyncRequest(info);
             
             this.AfterCommit();
         }
     }