예제 #1
0
        public RoundBasedRegister(IIntercomMessageHub intercomMessageHub,
                                  IBallotGenerator ballotGenerator,
                                  ISynodConfiguration synodConfig,
                                  LeaseConfiguration leaseConfig,
                                  ILogger logger)
        {
            this.logger = logger;
            this.synodConfig = synodConfig;
            this.leaseConfig = leaseConfig;
            this.intercomMessageHub = intercomMessageHub;
            intercomMessageHub.Start();
            readBallot = ballotGenerator.Null();
            writeBallot = ballotGenerator.Null();

            listener = intercomMessageHub.Subscribe();

            listener.Where(m => Unsafe.Equals(m.Identity, LeaseReadMessage.MessageIdentity))
                    .Subscribe(OnReadReceived);
            listener.Where(m => Unsafe.Equals(m.Identity, LeaseWriteMessage.MessageIdentity))
                    .Subscribe(OnWriteReceived);

            ackReadStream = listener.Where(m => Unsafe.Equals(m.Identity, LeaseAckReadMessage.MessageIdentity));
            nackReadStream = listener.Where(m => Unsafe.Equals(m.Identity, LeaseNackReadMessage.MessageIdentity));
            ackWriteStream = listener.Where(m => Unsafe.Equals(m.Identity, LeaseAckWriteMessage.MessageIdentity));
            nackWriteStream = listener.Where(m => Unsafe.Equals(m.Identity, LeaseNackWriteMessage.MessageIdentity));
        }
예제 #2
0
        public void TestTwoBallotsGeneratedWithinSafetyPeriod_HaveDifferentMessageNumber()
        {
            var identity = new byte[] {0};
            var leaseConfig = new LeaseConfiguration
                              {
                                  ClockDrift = TimeSpan.FromMilliseconds(500)
                              };
            var ballotGenerator = new BallotGenerator(leaseConfig);
            var ballot1 = ballotGenerator.New(identity);
            Thread.Sleep((int)leaseConfig.ClockDrift.TotalMilliseconds / 10);
            var ballot2 = ballotGenerator.New(identity);

            Assert.GreaterOrEqual(leaseConfig.ClockDrift, ballot2.Timestamp - ballot1.Timestamp);
            Assert.AreNotEqual(ballot1.MessageNumber, ballot2.MessageNumber);
        }
        internal static RoundBasedRegisterTestSetup CreateRoundBasedRegister(IEnumerable<string> synod, string localNodeUri)
        {
            var intercomMessageHubSocketFactory = new IntercomMessageHubSocketFactory();
            var socketFactory = new Mock<ISocketFactory>();
            socketFactory.Setup(m => m.CreateSubscriberSocket()).Returns(intercomMessageHubSocketFactory.CreateSubscriberSocket);
            var appConfig = new ApplicationConfiguration
                            {
                                Synod = new SynodConfiguration
                                        {
                                            Members = synod,
                                            ClockDrift = TimeSpan.FromMilliseconds(100),
                                            MessageRoundtrip = TimeSpan.FromSeconds(4),
                                            NodeResponseTimeout = TimeSpan.FromSeconds(2),
                                            LocalNode = localNodeUri,
                                            MaxLeaseTimeSpan = TimeSpan.FromSeconds(10)
                                        }
                            };
            var leaseConfig = new LeaseConfiguration
                              {
                                  ClockDrift = appConfig.Synod.ClockDrift,
                                  MaxLeaseTimeSpan = appConfig.Synod.MaxLeaseTimeSpan,
                                  MessageRoundtrip = appConfig.Synod.MessageRoundtrip,
                                  NodeResponseTimeout = appConfig.Synod.NodeResponseTimeout
                              };
            var socketConfig = new SocketConfiguration
                               {
                                   ReceivingHighWatermark = 1000,
                                   SendingHighWatermark = 1000,
                                   Linger = TimeSpan.Zero
                               };
            var synodConfig = new Rendezvous.Consensus.SynodConfiguration(new SynodConfigurationProvider(appConfig));
            var loggerMock = new Mock<ILogger>();
            var intercomMessageHub = new IntercomMessageHub(new SocketFactory(socketConfig),
                                                            synodConfig,
                                                            loggerMock.Object);
            var ballotGenerator = new BallotGenerator(leaseConfig);
            var roundBasedRegister = new RoundBasedRegister(intercomMessageHub,
                                                            ballotGenerator,
                                                            synodConfig,
                                                            leaseConfig,
                                                            loggerMock.Object);

            Thread.Sleep(TimeSpan.FromMilliseconds(400));

            return new RoundBasedRegisterTestSetup(ballotGenerator, synodConfig.LocalNode, roundBasedRegister);
        }
예제 #4
0
 private void ValidateConfiguration(LeaseConfiguration config)
 {
     if (config.NodeResponseTimeout.TotalMilliseconds * 2 > config.MessageRoundtrip.TotalMilliseconds)
     {
         throw new Exception("NodeResponseTimeout[{config.NodeResponseTimeout.TotalMilliseconds} msec] " +
                             "should be at least 2 times shorter than " +
                             "MessageRoundtrip[{config.MessageRoundtrip.TotalMilliseconds} msec]");
     }
     if (config.MaxLeaseTimeSpan
         - TimeSpan.FromTicks(config.MessageRoundtrip.Ticks * 2)
         - config.ClockDrift <= TimeSpan.Zero)
     {
         throw new Exception($"MaxLeaseTimeSpan[{config.MaxLeaseTimeSpan.TotalMilliseconds} msec] " +
                             "should be longer than " +
                             $"(2 * MessageRoundtrip[{config.MessageRoundtrip.TotalMilliseconds} msec] " +
                             $"+ ClockDrift[{config.ClockDrift.TotalMilliseconds} msec])");
     }
 }
예제 #5
0
        public LeaseProvider(IRoundBasedRegister register,
                             IBallotGenerator ballotGenerator,
                             LeaseConfiguration config,
                             ISynodConfiguration synodConfig,
                             RendezvousConfiguration rendezvousConfig,
                             ILogger logger)
        {
            ValidateConfiguration(config);

            WaitBeforeNextLeaseIssued(config);

            localNode = synodConfig.LocalNode;
            this.logger = logger;
            this.config = config;
            this.rendezvousConfig = rendezvousConfig;
            this.ballotGenerator = ballotGenerator;
            this.register = register;
            leaseRenewWaitTimeout = TimeSpan.FromMilliseconds(10);
            renewGateway = new SemaphoreSlim(1);
            leaseTimer = new Timer(state => ScheduledReadOrRenewLease(), null, TimeSpan.FromMilliseconds(-1), TimeSpan.FromMilliseconds(-1));
        }
예제 #6
0
 private void WaitBeforeNextLeaseIssued(LeaseConfiguration config)
 {
     Sleep(config.MaxLeaseTimeSpan);
 }
예제 #7
0
 public BallotGenerator(LeaseConfiguration config)
 {
     this.config = config;
     lastBallotTimestamp = new BallotTimestamp {MessageNumber = 0, Timestamp = DateTime.UtcNow};
     NullBallot = new Ballot(DateTime.MinValue, 0, Empty);
 }