/// <summary> /// The method to do two phrase commit /// This method shall be hosted in a new thread. /// The caller can wait on the DoneEvent. /// </summary> public void StartCommit(bool prepareFail = false, bool commitFail = false) { this.prepareFail = prepareFail; this.commitFail = commitFail; bool isStepComplete = false; var list = this.ResouceManagers.ResourceManagers; for (int i = 0; i < list.Count; i++) { rmCommitStates[i] = CommitState.Committed; } TwoPhaseCommit.WriteLog(); Prepare(); if ((isStepComplete = this.stepWaitEvent.WaitOne(stepTimeout))) { TwoPhaseCommit.WriteLog(); isStepComplete = WaitStepWithExpBackoff(Commit); if (isStepComplete) { TwoPhaseCommit.WriteLog(); TwoPhaseCommit.DoneCommit(this.Context); DoneEvent.Set(); } else { string outstring = string.Format("2PC:Retry Commit {0}\r", this.Context.Id); this.Message += outstring; Console.Write(string.Format("2PC:Retry Commit {0}\r", this.Context.Id)); WaitStepWithExpBackoff(Commit); } } else { // Presume abort Rollback(); TwoPhaseCommit.WriteLog(); TwoPhaseCommit.DoneCommit(this.Context); DoneEvent.Set(); } }
/// <summary> /// TM shall call this function when it restarts. /// if return is true /// 1. TM shall delete the transaction or retry commit if the state after recover is Rollbacked. /// 2. TM shall delete the transaction if the state after recover is done; /// if return is false /// TM shall retry the recover process; /// </summary> /// <return>false if the recover process failed.</return> public bool Recover() { foreach (RM rm in this.ResouceManagers.ResourceManagers) { RM inTM = null; while (inTM == null) { try { inTM = MyTM.StaticGetResourceMananger(rm.GetName()); } catch (WebException) { } if (inTM == null) { MyTM.StaticRegister(rm); } } } switch (State) { case CommitState.Committed: Rollback(); TwoPhaseCommit.WriteLog(); break; case CommitState.Prepared: Commit(); TwoPhaseCommit.WriteLog(); break; default: this.stepWaitEvent.Set(); break; } return(this.stepWaitEvent.WaitOne(stepTimeout)); }