/// <summary> /// Commits a transaction /// Initialize and recover from previous failure if necessary. /// See document for Init for details /// Use new thread to do two phrase commit on the transaction /// /// </summary> /// <param name="context"></param> /// <param name="rms"></param> /// <returns></returns> public static CommitedTransaction Commit(Transaction context, ResourceManagerList rms) { StartUp(); CommitedTransaction trans = new CommitedTransaction(context, rms); lock (syncRoot) { if (!committedTransactions.ContainsKey(context)) { committedTransactions.Add(context, trans); } else { trans = committedTransactions[context]; } } ThreadPool.QueueUserWorkItem(o => { if (trans.State < CommitState.Committed) { trans.State = CommitState.Committed; trans.StartCommit(PrepareFail, CommitFail); } }); return trans; }
/// <summary> /// Commits a transaction /// Initialize and recover from previous failure if necessary. /// See document for Init for details /// Use new thread to do two phrase commit on the transaction /// /// </summary> /// <param name="context"></param> /// <param name="rms"></param> /// <returns></returns> public static CommitedTransaction Commit(Transaction context, ResourceManagerList rms) { StartUp(); CommitedTransaction trans = new CommitedTransaction(context, rms); lock (syncRoot) { if (!committedTransactions.ContainsKey(context)) { committedTransactions.Add(context, trans); } else { trans = committedTransactions[context]; } } ThreadPool.QueueUserWorkItem(o => { if (trans.State < CommitState.Committed) { trans.State = CommitState.Committed; trans.StartCommit(PrepareFail, CommitFail); } }); return(trans); }
/// <summary> /// Call from WC in response to a client's commit /// </summary> /// <param name="context"></param> public void Commit(TP.Transaction context) { WaitTillReady(); lock (_resourceManagersEnlistedInTransactions) { if (_resourceManagersEnlistedInTransactions.ContainsKey(context)) { CommitedTransaction trans = TwoPhaseCommit.Commit(context, _resourceManagersEnlistedInTransactions[context]); trans.DoneEvent.WaitOne(TransactionTimeout * 1000); _resourceManagersEnlistedInTransactions.Remove(context); } } Console.WriteLine(string.Format("TM: Transaction {0} commited", context.Id)); }
/// <summary> /// Initialize the class /// If the log file exists, it will try to recover from previous run first by looking for /// committed transactions which are in CommitState.Committed || CommitState.Prepared state. /// </summary> public static void StartUp() { lock (syncRoot) { if (!isInitialized) { if (File.Exists(LogFileName)) { string line; lock (committedTransactions) { committedTransactions = new Dictionary <Transaction, CommitedTransaction>(); using (StreamReader reader = new StreamReader(LogFileName)) { while ((line = reader.ReadLine()) != null) { if (!string.IsNullOrWhiteSpace(line)) { CommitedTransaction trans = CommitedTransaction.FromString(line); // only recover the transaction which needs to be recovered if (trans.State == CommitState.Committed || trans.State == CommitState.Prepared) { committedTransactions[trans.Context] = trans; } } } } } } isInitialized = true; // The DB recovery code shall have locked the resources before this statement. // Therefore, the subsequential query on the modified resources will be blocked until the recover process is finished foreach (CommitedTransaction trans in committedTransactions.Values) { if (trans.State == CommitState.Committed || trans.State == CommitState.Prepared) { trans.Recover(); } } } } }
public static CommitedTransaction FromString(string input) { string[] items = input.Split(new char[] { '\t' }, StringSplitOptions.None); Transaction trans = new Transaction(); trans.Id = new Guid(items[0]); string[] rms = items[2].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); ResourceManagerList rml = new ResourceManagerList(); foreach (string s in rms) { RM rm = new MyRM.MyRM(); rm.SetName(s); rml.Add(rm); } CommitedTransaction result = new CommitedTransaction(trans, rml); switch (items[1]) { case "None": result.State = CommitState.None; break; case "Committed": result.State = CommitState.Committed; break; case "Prepared": result.State = CommitState.Prepared; break; case "Done": result.State = CommitState.Done; break; } for (int i = 0; i < result.rmCommitStates.Count; i++) { result.rmCommitStates[i] = result.State; } return(result); }
public static CommitedTransaction FromString(string input) { string[] items = input.Split(new char[] { '\t' }, StringSplitOptions.None); Transaction trans = new Transaction(); trans.Id = new Guid(items[0]); string[] rms = items[2].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); ResourceManagerList rml = new ResourceManagerList(); foreach (string s in rms) { RM rm = new MyRM.MyRM(); rm.SetName(s); rml.Add(rm); } CommitedTransaction result = new CommitedTransaction(trans, rml); switch (items[1]) { case "None": result.State = CommitState.None; break; case "Committed": result.State = CommitState.Committed; break; case "Prepared": result.State = CommitState.Prepared; break; case "Done": result.State = CommitState.Done; break; } for (int i = 0; i < result.rmCommitStates.Count; i++) { result.rmCommitStates[i] = result.State; } return result; }