Ejemplo n.º 1
0
 public void Send(JsonOperationContext context, InstallSnapshot installSnapshot)
 {
     Send(context, new DynamicJsonValue
     {
         ["Type"] = nameof(InstallSnapshot),
         [nameof(InstallSnapshot.LastIncludedIndex)] = installSnapshot.LastIncludedIndex,
         [nameof(InstallSnapshot.LastIncludedTerm)]  = installSnapshot.LastIncludedTerm,
         [nameof(InstallSnapshot.Topology)]          = installSnapshot.Topology
     });
 }
Ejemplo n.º 2
0
        public void Send(JsonOperationContext context, InstallSnapshot installSnapshot)
        {
            if (_log.IsInfoEnabled)
            {
                _log.Info($"Install snapshot on: ({installSnapshot.LastIncludedIndex} / {installSnapshot.LastIncludedTerm})");
            }

            Send(context, new DynamicJsonValue
            {
                ["Type"] = nameof(InstallSnapshot),
                [nameof(InstallSnapshot.LastIncludedIndex)] = installSnapshot.LastIncludedIndex,
                [nameof(InstallSnapshot.LastIncludedTerm)]  = installSnapshot.LastIncludedTerm,
                [nameof(InstallSnapshot.Topology)]          = installSnapshot.Topology
            });
        }
Ejemplo n.º 3
0
        private void ReadAndCommitSnapshot(ClusterOperationContext context, InstallSnapshot snapshot, CancellationToken token)
        {
            using (context.OpenWriteTransaction())
            {
                var lastTerm        = _engine.GetTermFor(context, snapshot.LastIncludedIndex);
                var lastCommitIndex = _engine.GetLastEntryIndex(context);

                if (_engine.GetSnapshotRequest(context) == false &&
                    snapshot.LastIncludedTerm == lastTerm && snapshot.LastIncludedIndex < lastCommitIndex)
                {
                    if (_engine.Log.IsInfoEnabled)
                    {
                        _engine.Log.Info(
                            $"{ToString()}: Got installed snapshot with last index={snapshot.LastIncludedIndex} while our lastCommitIndex={lastCommitIndex}, will just ignore it");
                    }

                    //This is okay to ignore because we will just get the committed entries again and skip them
                    ReadInstallSnapshotAndIgnoreContent(token);
                }
                else if (InstallSnapshot(context, token))
                {
                    if (_engine.Log.IsInfoEnabled)
                    {
                        _engine.Log.Info(
                            $"{ToString()}: Installed snapshot with last index={snapshot.LastIncludedIndex} with LastIncludedTerm={snapshot.LastIncludedTerm} ");
                    }

                    _engine.SetLastCommitIndex(context, snapshot.LastIncludedIndex, snapshot.LastIncludedTerm);
                    _engine.ClearLogEntriesAndSetLastTruncate(context, snapshot.LastIncludedIndex, snapshot.LastIncludedTerm);
                }
                else
                {
                    var lastEntryIndex = _engine.GetLastEntryIndex(context);
                    if (lastEntryIndex < snapshot.LastIncludedIndex)
                    {
                        var message =
                            $"The snapshot installation had failed because the last included index {snapshot.LastIncludedIndex} in term {snapshot.LastIncludedTerm} doesn't match the last entry {lastEntryIndex}";
                        if (_engine.Log.IsInfoEnabled)
                        {
                            _engine.Log.Info($"{ToString()}: {message}");
                        }

                        throw new InvalidOperationException(message);
                    }
                }

                // snapshot always has the latest topology
                if (snapshot.Topology == null)
                {
                    const string message = "Expected to get topology on snapshot";
                    if (_engine.Log.IsInfoEnabled)
                    {
                        _engine.Log.Info($"{ToString()}: {message}");
                    }

                    throw new InvalidOperationException(message);
                }

                using (var topologyJson = context.ReadObject(snapshot.Topology, "topology"))
                {
                    if (_engine.Log.IsInfoEnabled)
                    {
                        _engine.Log.Info($"{ToString()}: topology on install snapshot: {topologyJson}");
                    }

                    var topology = JsonDeserializationRachis <ClusterTopology> .Deserialize(topologyJson);

                    RachisConsensus.SetTopology(_engine, context, topology);
                }

                _engine.SetSnapshotRequest(context, false);

                context.Transaction.InnerTransaction.LowLevelTransaction.OnDispose += t =>
                {
                    if (t is LowLevelTransaction llt && llt.Committed)
                    {
                        // we might have moved from passive node, so we need to start the timeout clock
                        _engine.Timeout.Start(_engine.SwitchToCandidateStateOnTimeout);
                    }
                };

                context.Transaction.Commit();
            }
        }