public void TestWriteIsAborted_AfterWriteWithBallotGreaterThanCurrent() { using (CreateRoundBasedRegister(GetSynodMembers(), GetSynodMembers().First())) { using (CreateRoundBasedRegister(GetSynodMembers(), GetSynodMembers().Second())) { using (var testSetup = CreateRoundBasedRegister(GetSynodMembers(), GetSynodMembers().Third())) { var ballotGenerator = testSetup.BallotGenerator; var localNode = testSetup.LocalNode; var roundBasedRegister = testSetup.RoundBasedRegister; var ballot0 = ballotGenerator.New(localNode.SocketIdentity); var lease = new Lease(localNode.SocketIdentity, ownerEndpoint, DateTime.UtcNow); var txResult = roundBasedRegister.Write(ballot0, lease); Assert.AreEqual(TxOutcome.Commit, txResult.TxOutcome); var ballot1 = new Ballot(ballot0.Timestamp - TimeSpan.FromSeconds(10), ballot0.MessageNumber, localNode.SocketIdentity); Assert.IsTrue(ballot0 > ballot1); txResult = roundBasedRegister.Write(ballot1, lease); Assert.AreEqual(TxOutcome.Abort, txResult.TxOutcome); } } } }
private void LogNackWrite(Ballot ballot) { if (writeBallot > ballot) { logger.Debug($"process {synodConfig.LocalNode.Uri.AbsoluteUri} " + "NACK_WRITE ==WB== " + $"{writeBallot.Timestamp.ToString("HH:mm:ss fff")}-" + $"{writeBallot.MessageNumber}-" + $"{writeBallot.Identity.GetString()} " + "> " + $"{ballot.Timestamp.ToString("HH:mm:ss fff")}-" + $"{ballot.MessageNumber}-" + $"{ballot.Identity.GetString()}"); } if (readBallot > ballot) { logger.Debug($"process {synodConfig.LocalNode.Uri.AbsoluteUri} " + "NACK_WRITE ==RB== " + $"{readBallot.Timestamp.ToString("HH:mm:ss fff")}-" + $"{readBallot.MessageNumber}-" + $"{readBallot.Identity.GetString()} " + "> " + $"{ballot.Timestamp.ToString("HH:mm:ss fff")}-" + $"{ballot.MessageNumber}-" + $"{ballot.Identity.GetString()}"); } }
private Lease AсquireOrLearnLease(Ballot ballot, DateTime now) { var read = register.Read(ballot); if (read.TxOutcome == TxOutcome.Commit) { var lease = read.Lease; if (LeaseIsNotSafelyExpired(lease, now)) { LogStartSleep(); Sleep(config.ClockDrift); LogAwake(); // TODO: Add recursion exit condition return AсquireOrLearnLease(ballotGenerator.New(localNode.SocketIdentity), DateTime.UtcNow); } if (LeaseNullOrExpired(lease, now) || IsLeaseOwner(lease)) { LogLeaseProlonged(lease); var ownerEndpoint = new OwnerEndpoint {UnicastUri = rendezvousConfig.UnicastUri, MulticastUri = rendezvousConfig.MulticastUri}; lease = new Lease(localNode.SocketIdentity, ownerEndpoint, now + config.MaxLeaseTimeSpan); } var write = register.Write(ballot, lease); if (write.TxOutcome == TxOutcome.Commit) { return lease; } } return null; }
public BallotGenerator(LeaseConfiguration config) { this.config = config; lastBallotTimestamp = new BallotTimestamp {MessageNumber = 0, Timestamp = DateTime.UtcNow}; NullBallot = new Ballot(DateTime.MinValue, 0, Empty); }