private void SnapshotAndTruncateLog(long to, ManualResetEventSlim allowFurtherModifications) { var task = new Task(() => { OnSnapshotCreationStarted(); try { var currentTerm = PersistentState.CurrentTerm; _log.Info("Starting to create snapshot up to {0} in term {1}", to, currentTerm); StateMachine.CreateSnapshot(to, currentTerm, allowFurtherModifications); PersistentState.MarkSnapshotFor(to, currentTerm, Options.MaxLogLengthBeforeCompaction - (Options.MaxLogLengthBeforeCompaction / 8)); _log.Info("Finished creating snapshot for {0} in term {1}", to, currentTerm); OnSnapshotCreationEnded(); } catch (Exception e) { _log.Error("Failed to create snapshot", e); OnSnapshotCreationError(e); } finally { Interlocked.Exchange(ref _snapshottingTask, null); } }); if (Interlocked.CompareExchange(ref _snapshottingTask, task, null) != null) { allowFurtherModifications.Set(); return; } task.Start(); }
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); } }