Example #1
0
        public void Handle(ReplicationMessage.ReplicaSubscribed message)
        {
            if (_activeChunk != null)
            {
                _activeChunk.MarkForDeletion();
                _activeChunk = null;
            }
            _framer.Reset();

            _subscriptionId       = message.SubscriptionId;
            _ackedSubscriptionPos = _subscriptionPos = message.SubscriptionPosition;

            Log.Info("=== SUBSCRIBED to [{masterEndPoint},{masterId:B}] at {subscriptionPosition} (0x{subscriptionPosition:X}). SubscriptionId: {subscriptionId:B}.",
                     message.MasterEndPoint, message.MasterId, message.SubscriptionPosition, message.SubscriptionPosition, message.SubscriptionId);

            var writerCheck = Db.Config.WriterCheckpoint.ReadNonFlushed();

            if (message.SubscriptionPosition > writerCheck)
            {
                ReplicationFail(
                    "Master [{0},{1:B}] subscribed us at {2} (0x{3:X}), which is greater than our writer checkpoint {4} (0x{5:X}). REPLICATION BUG.",
                    "Master [{masterEndpoint},{masterId:B}] subscribed us at {subscriptionPosition} (0x{subscriptionPosition:X}), which is greater than our writer checkpoint {writerCheckpoint} (0x{writerCheckpoint:X}). REPLICATION BUG.",
                    message.MasterEndPoint, message.MasterId, message.SubscriptionPosition, message.SubscriptionPosition, writerCheck, writerCheck);
            }

            if (message.SubscriptionPosition < writerCheck)
            {
                Log.Info("Master [{masterEndPoint},{masterId:B}] subscribed us at {subscriptionPosition} (0x{subscriptionPosition:X}), which is less than our writer checkpoint {writerCheckpoint} (0x{writerCheckpoint:X}). TRUNCATION IS NEEDED.",
                         message.MasterEndPoint, message.MasterId, message.SubscriptionPosition, message.SubscriptionPosition, writerCheck, writerCheck);

                var lastCommitPosition = _getLastCommitPosition();
                if (message.SubscriptionPosition > lastCommitPosition)
                {
                    Log.Info("ONLINE TRUNCATION IS NEEDED. NOT IMPLEMENTED. OFFLINE TRUNCATION WILL BE PERFORMED. SHUTTING DOWN NODE.");
                }
                else
                {
                    Log.Info("OFFLINE TRUNCATION IS NEEDED (SubscribedAt {subscriptionPosition} (0x{subscriptionPosition:X}) <= LastCommitPosition {lastCommitPosition} (0x{lastCommitPosition:X})). SHUTTING DOWN NODE.", message.SubscriptionPosition, message.SubscriptionPosition, lastCommitPosition, lastCommitPosition);
                }

                EpochRecord lastEpoch = EpochManager.GetLastEpoch();
                if (AreAnyCommittedRecordsTruncatedWithLastEpoch(message.SubscriptionPosition, lastEpoch, lastCommitPosition))
                {
                    Log.Error("Master [{masterEndPoint},{masterId:B}] subscribed us at {subscriptionPosition} (0x{subscriptionPosition:X}), which is less than our last epoch and LastCommitPosition {lastCommitPosition} (0x{lastCommitPosition:X}) >= lastEpoch.EpochPosition {lastEpochPosition} (0x{lastEpochPosition:X}). That might be bad, especially if the LastCommitPosition is way beyond EpochPosition.",
                              message.MasterEndPoint, message.MasterId, message.SubscriptionPosition, message.SubscriptionPosition, lastCommitPosition, lastCommitPosition, lastEpoch.EpochPosition, lastEpoch.EpochPosition);
                    Log.Error("ATTEMPT TO TRUNCATE EPOCH WITH COMMITTED RECORDS. THIS MAY BE BAD, BUT IT IS OK IF JUST-ELECTED MASTER FAILS IMMEDIATELY AFTER ITS ELECTION.");
                }

                Db.Config.TruncateCheckpoint.Write(message.SubscriptionPosition);
                Db.Config.TruncateCheckpoint.Flush();

                BlockWriter = true;
                Bus.Publish(new ClientMessage.RequestShutdown(exitProcess: true, shutdownHttp: true));
                return;
            }

            // subscription position == writer checkpoint
            // everything is ok
        }
Example #2
0
        public void subscription_is_sent_replica_subscribed_message_for_leaders_epoch_after_common_epoch()
        {
            var subscribed = GetTcpSendsFor(_replicaManager).Select(x => x.Message)
                             .OfType <ReplicationMessage.ReplicaSubscribed>().ToArray();

            Assert.AreEqual(1, subscribed.Length);
            Assert.AreEqual(EpochManager.GetLastEpoch().EpochPosition, subscribed[0].SubscriptionPosition);
            Assert.AreEqual(_replicaId, subscribed[0].SubscriptionId);
            Assert.AreEqual(LeaderId, subscribed[0].LeaderId);
        }
Example #3
0
        public override void When()
        {
            EpochManager.WriteNewEpoch(0);
            Writer.Write(CreateLogRecord(0), out _);
            Writer.Write(CreateLogRecord(1), out _);
            Writer.Write(CreateLogRecord(2), out _);
            Writer.Write(CreateLogRecord(3), out _);
            Writer.Write(CreateLogRecord(4), out _subscribedPosition);
            EpochManager.WriteNewEpoch(1);

            _lastEpoch = EpochManager.GetLastEpoch();
            var epochs = EpochManager.GetLastEpochs(10)
                         .Select(e => new Epoch(e.EpochPosition, e.EpochNumber, e.EpochId)).ToArray();

            AddSubscription(_replicaId, true, epochs, _subscribedPosition, out _replicaManager);
        }
Example #4
0
 public void epoch_should_be_updated()
 {
     AssertEx.IsOrBecomesTrue(() => EpochManager.GetLastEpoch() != null);
     Assert.AreEqual(_epochId, EpochManager.GetLastEpoch().EpochId);
     Assert.AreEqual(_epochNumber, EpochManager.GetLastEpoch().EpochNumber);
 }