Exemple #1
0
        private void Rollback()
        {
            var list = this.ResouceManagers.ResourceManagers;

            for (int i = 0; i < list.Count; i++)
            {
                RM     r         = list[i];
                string outstring = string.Format("2PC:Rollback {0}:{1}\r", this.Context.Id, this.ResouceManagers.RMNames[i]);
                this.Message += outstring;
                Console.Write(outstring);
                int temp = i;
                ThreadPool.QueueUserWorkItem(o =>
                {
                    while (true)
                    {
                        try
                        {
                            r.Abort(this.Context);
                            break;
                        }
                        catch (WebException)
                        {
                        }
                        Console.WriteLine("ResourceManager {0} is not ready, wait 0.5 second", this.ResouceManagers.RMNames[temp]);
                        Thread.Sleep(500);
                    }
                    // presume abort, if we don't check return of the abort
                    // Once the abort message is sent, it is consider done.
                    this.SetState(temp, CommitState.Rollbacked);
                });
            }
        }
Exemple #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.");
        }