Ejemplo n.º 1
0
        private void Commit()
        {
            var list = this.ResouceManagers.ResourceManagers;

            for (int i = 0; i < list.Count; i++)
            {
                RM     r         = list[i];
                int    temp      = i;
                string outstring = string.Format("2PC:Commit {0}:{1}\r", this.Context.Id, this.ResouceManagers.RMNames[temp]);
                this.Message += outstring;
                Console.Write(outstring);
                ThreadPool.QueueUserWorkItem(o =>
                {
                    lock (syncCommit)
                    {
                        if (rmCommitStates[temp] == CommitState.Prepared)
                        {
                            while (true)
                            {
                                try
                                {
                                    XaResponse response = r.Commit(this.Context);
                                    if (response == XaResponse.XA_OK)
                                    {
                                        this.SetState(temp, CommitState.Done);
                                    }

                                    break;
                                }
                                catch (WebException)
                                {
                                }
                                Console.WriteLine("ResourceManager {0} is not ready, wait 0.5 second",
                                                  this.ResouceManagers.RMNames[temp]);
                                Thread.Sleep(500);
                            }
                        }
                    }
                });

                if (commitFail)
                {
                    SelfDestroying();
                }
            }
        }
Ejemplo n.º 2
0
        // This function reviews all outstanding transaction and reissues Commit() or Abort() to the
        // unackowledged RMs
        public void recovery()
        {
            Console.Out.WriteLine("Recovery started...");
            List <string> deleteTransactionList = new List <string>(); // Keep track of transactions that are fully acknowledged by all its RMs

            lock (OutstandingTransactions)
            {
                if (OutstandingTransactions.transactionList.Keys.Count == 0)
                {
                    Console.WriteLine("Recovery: No outstanding transactions to recover. Recovery completed.");
                    return;
                }

                foreach (string transactionId in OutstandingTransactions.transactionList.Keys)
                {
                    // For each outstanding transaction, get its transaction id and its OutstandingTransactions value
                    OutstandingTransactions.OutstandingTransactionsValue entry = OutstandingTransactions.transactionList[transactionId];
                    Transaction context = new Transaction();
                    context.Id = new Guid(transactionId);

                    Console.Out.WriteLine(string.Format("Recovery: Recovering transaction {0}...", transactionId));

                    // For each of the remaining NACK RMs, reissue the Commit or Abort
                    for (int i = 0; i < entry.nackRMList.Count; ++i)
                    {
                        string rmName = entry.nackRMList[i];
                        RM     rm     = GetResourceMananger(rmName);
                        if (rm == null)
                        {
                            Console.Out.WriteLine(string.Format("Recovery: Failed to find resource manager {0}", rmName));
                        }
                        else
                        {
                            ExecuteActionWithTimeout exec;

                            if (entry.transactionType == OutstandingTransactions.OutstandingTransactionsValue.TransactionType.Commit)
                            {
                                Console.Out.WriteLine(string.Format("Recovery: Re-committing resource manager {0}...", rmName));
                                exec = new ExecuteActionWithTimeout(rmName, () => rm.Commit(context));
                            }
                            else
                            {
                                Console.Out.WriteLine(string.Format("Recovery: Re-aborting resource manager {0}...", rmName));
                                exec = new ExecuteActionWithTimeout(rmName, () => rm.Abort(context));
                            }

                            // Execute the commit or abort
                            try
                            {
                                exec.Run();
                                Console.Out.WriteLine("Recovery: Successful!");

                                // Remove RM from the current transaction since we received the Done message (ie the call didn't time out)
                                OutstandingTransactions.transactionList[transactionId].nackRMList.RemoveAt(i);
                                --i;
                            }
                            catch (TimeoutException)
                            {
                                System.Console.WriteLine("Recovery: Failed!");
                            }
                        }
                    }

                    // PRESUMED ABORT: If the transaction is Abort, we don't care about the Done message and we forget about
                    // the transaction immediately.
                    // For commit transactions, mark transaction for removal if we received Done from all RMs
                    if (entry.transactionType == OutstandingTransactions.OutstandingTransactionsValue.TransactionType.Abort ||
                        entry.nackRMList.Count == 0)
                    {
                        deleteTransactionList.Add(transactionId);
                    }
                }

                // Delete transaction marked for removal from the outstanding transaction list
                foreach (string s in deleteTransactionList)
                {
                    OutstandingTransactions.transactionList.Remove(s);
                }
                // Update file to reflect outstanding transactions status
                // This is a full rewrite of the outstanding transaction file and hence it will implicitly garbage collect
                // the transactions that are no longer outstanding.
                OutstandingTransactions.WriteToFile();
            }
            Console.Out.WriteLine("Recovery completed.");
        }