public void CanProperlySnapshot() { using (var state = new PersistentState("self", StorageEnvironmentOptions.CreateMemoryOnly(), CancellationToken.None) { CommandSerializer = new JsonCommandSerializer() }) { state.UpdateTermTo(null, 1); state.AppendToLeaderLog(new NopCommand()); for (int i = 0; i < 5; i++) { state.AppendToLeaderLog(new DictionaryCommand.Set { Key = i.ToString(), Value = i }); } state.MarkSnapshotFor(6, 1, 5); state.AppendToLeaderLog(new DictionaryCommand.Set { Key = "1", Value = 4 }); var lastLogEntry = state.LastLogEntry(); Assert.Equal(7, lastLogEntry.Index); } }
public static void SetTopologyExplicitly(RaftEngineOptions options, Topology topology, bool throwIfTopologyExists) { using (var ps = new PersistentState("ClusterBootstrap", options.StorageOptions, CancellationToken.None)) { if (ps.GetCurrentTopology().HasVoters&& throwIfTopologyExists) { throw new InvalidOperationException("Cannot set topology on a cluster that already have a topology"); } ps.SetCurrentTopology(topology, 0); } }
public RaftEngine(RaftEngineOptions raftEngineOptions) { //#if DEBUG // Console.WriteLine("Press any key to continue loading Raft -> opportunity to attach debugger"); // Console.ReadLine(); //#endif _raftEngineOptions = raftEngineOptions; Debug.Assert(raftEngineOptions.Stopwatch != null); _log = LogManager.GetLogger(raftEngineOptions.Name + "." + GetType().FullName); _eventLoopCancellationTokenSource = new CancellationTokenSource(); Name = raftEngineOptions.Name; PersistentState = new PersistentState(raftEngineOptions.Name, raftEngineOptions.StorageOptions, _eventLoopCancellationTokenSource.Token) { CommandSerializer = new JsonCommandSerializer() }; _currentTopology = PersistentState.GetCurrentTopology(); //warm up to make sure that the serializer don't take too long and force election timeout PersistentState.CommandSerializer.Serialize(new NopCommand()); var thereAreOthersInTheCluster = CurrentTopology.QuorumSize > 1; if (thereAreOthersInTheCluster == false && CurrentTopology.IsVoter(Name)) { PersistentState.UpdateTermTo(this, PersistentState.CurrentTerm + 1);// restart means new term SetState(RaftEngineState.Leader); } else { SetState(RaftEngineState.Follower); } _commitIndex = StateMachine.LastAppliedIndex; _eventLoopTask = Task.Run(() => EventLoop()); }
public static void SetTopologyExplicitly(RaftEngineOptions options, Topology topology, bool throwIfTopologyExists) { using (var ps = new PersistentState("ClusterBootstrap", options.StorageOptions, CancellationToken.None)) { if (ps.GetCurrentTopology().HasVoters && throwIfTopologyExists) throw new InvalidOperationException("Cannot set topology on a cluster that already have a topology"); ps.SetCurrentTopology(topology, 0); } }
public void AllPeers_and_AllVotingPeers_can_be_persistantly_saved_and_loaded() { var cancellationTokenSource = new CancellationTokenSource(); var path = "test" + Guid.NewGuid(); try { var expectedAllVotingPeers = new List<string> { "Node123", "Node1", "Node2", "NodeG", "NodeB", "NodeABC" }; using (var options = StorageEnvironmentOptions.ForPath(path)) { using (var persistentState = new PersistentState("self",options, cancellationTokenSource.Token) { CommandSerializer = new JsonCommandSerializer() }) { var currentConfiguration = persistentState.GetCurrentTopology(); Assert.Empty(currentConfiguration.AllVotingNodes); var currentTopology = new Topology(new Guid("355a589b-cadc-463d-a515-5add2ea47205"), expectedAllVotingPeers.Select(x => new NodeConnectionInfo { Name = x }), Enumerable.Empty<NodeConnectionInfo>(), Enumerable.Empty<NodeConnectionInfo>()); persistentState.SetCurrentTopology(currentTopology, 1); } } using (var options = StorageEnvironmentOptions.ForPath(path)) { using (var persistentState = new PersistentState("self", options, cancellationTokenSource.Token) { CommandSerializer = new JsonCommandSerializer() }) { var currentConfiguration = persistentState.GetCurrentTopology(); Assert.Equal(expectedAllVotingPeers.Count, currentConfiguration.AllVotingNodes.Count()); foreach (var nodeConnectionInfo in currentConfiguration.AllVotingNodes) { Assert.True(expectedAllVotingPeers.Contains(nodeConnectionInfo.Name)); } } } } finally { new DirectoryInfo(path).Delete(true); } }