public void CouldWriteReadLog0MoveGT() { #pragma warning disable 618 Settings.DoAdditionalCorrectnessChecks = false; #pragma warning restore 618 var path = TestUtils.GetPath(); var repoName = "CouldWriteAndReadLog0"; var processConfig = new ProcessConfig(path); StartupConfig.StreamLogBufferPoolFlags = LMDBEnvironmentFlags.NoSync; StartupConfig.StreamBlockIndexFlags = LMDBEnvironmentFlags.NoSync; var slm = new StreamLogManager(processConfig, repoName, null, 10 * 1024, true, true); var log0 = new NotificationLog(slm); // will disable packing log0.ActiveBuffer.Increment(); var count = 3_000_000; using (Benchmark.Run("Log0.Append", count)) { for (long i = 1; i <= count; i++) { log0.Append((StreamLogNotification)(ulong)i); } } using (Benchmark.Run("Log0 MoveGT", count)) { using (var reader = new NotificationLog.Reader(log0, CancellationToken.None, false)) { for (long i = 0; i < count; i++) { if (reader.MoveGT((ulong)i)) { if (reader.CurrentVersion != (ulong)(i + 1)) { Assert.Fail($"reader.CurrentVersion {reader.CurrentVersion} != [(ulong) (i + 1)] {i + 1}"); } } } } } // readerTask.Wait(); Benchmark.Dump(); slm.BufferPool.PrintBuffersAfterPoolDispose = true; log0.Dispose(); slm.Dispose(); }
public StreamLogManager(ProcessConfig processConfig, string dataStoreName, string dataStorePath = null, uint maxLogSizeMb = 1024, bool disableNotificationLog = false, bool disablePacker = false, IStreamBlockStorage blockStorage = null) { if (LeaksDetection.Enabled) { Spreads.Buffers.BufferPool.PinnedArrayMemoryPool.AddStackTraceOnRent = true; } DataStorePath = dataStorePath ?? Path.Combine(processConfig.DataRootPath, dataStoreName); ProcessConfig = processConfig; _wpidValue = ProcessConfig.Wpid; DisableNotificationLog = disableNotificationLog; DisablePacker = disablePacker; var bufferPoolPath = Path.Combine(DataStorePath, "log", "logbuffer"); var bufferPoolFlags = StartupConfig.StreamLogBufferPoolFlags; BufferPool = new BlockMemoryPool(bufferPoolPath, maxLogSizeMb, bufferPoolFlags, processConfig.Wpid, maxBufferLength: MaxBufferSize, maxBuffersPerBucket: Environment.ProcessorCount * 4); if (blockStorage == null) { var dataStoragePath = Path.Combine(DataStorePath, "storage"); Directory.CreateDirectory(dataStoragePath); var path = Path.GetFullPath(Path.Combine(dataStoragePath, "data.db")); var uri = new Uri(path); var absoluteUri = uri.AbsoluteUri; blockStorage = new SQLiteStorage($@"Data Source={absoluteUri}?cache=shared"); } var blockIndexPath = Path.Combine(DataStorePath, "log", "blockindex"); var blockIndexFlags = StartupConfig.StreamBlockIndexFlags; var blockIndexSizeMb = Math.Max(StartupConfig.StreamBlockTableMaxSizeMb, 128); BlockIndex = new StreamBlockIndex(blockIndexPath, blockIndexSizeMb, blockIndexFlags, BufferPool, blockStorage); var logStateStoragePath = Path.Combine(DataStorePath, "log", "logstate"); StateStorage = new StreamLogStateStorage(logStateStoragePath); // For Log0 tests we need state but we removed it from Log0 ctor, so always init it. // In real code _disableNotificationLog is always false. Log0State = StateStorage.GetState(StreamLogId.Log0Id); Log0State.CheckInit(StreamLogId.Log0Id, StreamLogNotification.Size, StreamLogFlags.IsBinary | StreamLogFlags.NoTimestamp | StreamLogFlags.DropPacked | StreamLogFlags.Pow2Payload); Log0State.HintRatePerMinute(MaxBufferSize); if (!DisableNotificationLog) { Log0 = new NotificationLog(this); OpenStreams.TryAdd((long)StreamLogId.Log0Id, Log0); Log0Reader = new NotificationLog.Reader(Log0, Cts.Token); var lastVersion = (ulong)Log0.CurrentVersion; if (lastVersion > 1) { Log0Reader.MoveGT(lastVersion - 1); } } Packer = new Packer(this, StateStorage, disablePacker); StartLog0(dataStoreName); // TODO we need more general unlocking locking that detects missed updates // and works for all waiters, not only for ack. See Log0.Reader comments. //_unlockTimer = new Timer(o => //{ // TryCompleteAckRequests(); //}, null, 0, 1000); }