/// <summary> /// Ukoliko klijent prestane da bude zainteresovan na neki DMS tip ili uopsteno na promene NMS modela onda radi Unsubscribed /// </summary> /// <param name="topics">Lista DMS tipova sa kojih se odjavljuje</param> /// <returns></returns> public void Unsubscribed(List <DMSType> topics) { OperationContext context = OperationContext.Current; ITwoPhaseCommit client = context.GetCallbackChannel <ITwoPhaseCommit>(); if (!subscribers.ContainsKey(client)) { return; } foreach (DMSType topic in topics) { if (!subscribers[client].Contains(topic)) { continue; } subscribers[client].Remove(topic); } if (subscribers[client].Count != 0) { return; } subscribers.Remove(client); }
public virtual void TestNullTPCs() { int numObjects = Random.Next(4) + 3; // between [3, 6] ITwoPhaseCommit[] tpcs = new ITwoPhaseCommit[numObjects]; bool setNull = false; for (int i = 0; i < tpcs.Length; i++) { bool isNull = Random.NextDouble() < 0.3; if (isNull) { setNull = true; tpcs[i] = null; } else { tpcs[i] = new TwoPhaseCommitImpl(false, false, false); } } if (!setNull) { // none of the TPCs were picked to be null, pick one at random int idx = Random.Next(numObjects); tpcs[idx] = null; } // following call would fail if TPCTool won't handle null TPCs properly TwoPhaseCommitTool.Execute(tpcs); }
/// <summary> /// Executes a 2-phase commit algorithm by first /// <see cref="ITwoPhaseCommit.PrepareCommit()"/> all objects and only if all succeed, /// it proceeds with <see cref="ITwoPhaseCommit.Commit()"/>. If any of the objects /// fail on either the preparation or actual commit, it terminates and /// <see cref="ITwoPhaseCommit.Rollback()"/> all of them. /// <para/> /// <b>NOTE:</b> It may happen that an object fails to commit, after few have /// already successfully committed. This tool will still issue a rollback /// instruction on them as well, but depending on the implementation, it may /// not have any effect. /// <para/> /// <b>NOTE:</b> if any of the objects are <c>null</c>, this method simply /// skips over them. /// </summary> /// <exception cref="PrepareCommitFailException"> /// if any of the objects fail to /// <see cref="ITwoPhaseCommit.PrepareCommit()"/> </exception> /// <exception cref="CommitFailException"> /// if any of the objects fail to <see cref="ITwoPhaseCommit.Commit()"/> </exception> public static void Execute(params ITwoPhaseCommit[] objects) { ITwoPhaseCommit tpc = null; try { // first, all should successfully prepareCommit() for (int i = 0; i < objects.Length; i++) { tpc = objects[i]; if (tpc != null) { tpc.PrepareCommit(); } } } catch (Exception t) { // first object that fails results in rollback all of them and // throwing an exception. Rollback(objects); throw new PrepareCommitFailException(t, tpc); } // If all successfully prepareCommit(), attempt the actual commit() try { for (int i = 0; i < objects.Length; i++) { tpc = objects[i]; if (tpc != null) { tpc.Commit(); } } } catch (Exception t) { // first object that fails results in rollback all of them and // throwing an exception. Rollback(objects); throw new CommitFailException(t, tpc); } }
/// <summary> /// Svi zainteresovani za promene statickog modela se prijavljuju na dogadjaje preko ove metode /// </summary> /// <param name="topics">List DMS tipova na koje se klijent prijavljuje</param> public void Subscribed(List <DMSType> topics) { OperationContext context = OperationContext.Current; ITwoPhaseCommit client = context.GetCallbackChannel <ITwoPhaseCommit>(); if (!subscribers.ContainsKey(client)) { subscribers.Add(client, topics); } foreach (DMSType topic in topics) { if (subscribers[client].Contains(topic)) { continue; } subscribers[client].Add(topic); } }
/// <summary> /// Sole constructor. </summary> public CommitFailException(Exception cause, ITwoPhaseCommit obj) : base("commit() failed on " + obj, cause) { }