Esempio n. 1
0
        private void FasterLogTest1(LogChecksumType logChecksum, IDevice device, ILogCommitManager logCommitManager)
        {
            log = new FasterLog(new FasterLogSettings {
                PageSizeBits = 20, SegmentSizeBits = 20, LogDevice = device, LogChecksum = logChecksum, LogCommitManager = logCommitManager
            });

            byte[] entry = new byte[entryLength];
            for (int i = 0; i < entryLength; i++)
            {
                entry[i] = (byte)i;
            }

            for (int i = 0; i < numEntries; i++)
            {
                log.Enqueue(entry);
            }
            log.Commit(true);

            using (var iter = log.Scan(0, long.MaxValue))
            {
                int count = 0;
                while (iter.GetNext(out byte[] result, out int length, out long currentAddress))
                {
                    count++;
                    Assert.IsTrue(result.SequenceEqual(entry));
                    if (count % 100 == 0)
                    {
                        log.TruncateUntil(iter.NextAddress);
                    }
                }
                Assert.IsTrue(count == numEntries);
            }

            log.Dispose();
        }
Esempio n. 2
0
        public void FasterLogTest1([Values] LogChecksumType logChecksum)
        {
            log = new FasterLog(new FasterLogSettings {
                LogDevice = device, LogChecksum = logChecksum
            });

            byte[] entry = new byte[entryLength];
            for (int i = 0; i < entryLength; i++)
            {
                entry[i] = (byte)i;
            }

            for (int i = 0; i < numEntries; i++)
            {
                log.Enqueue(entry);
            }
            log.Commit(true);

            using (var iter = log.Scan(0, long.MaxValue))
            {
                int count = 0;
                while (iter.GetNext(out byte[] result, out int length))
                {
                    count++;
                    Assert.IsTrue(result.SequenceEqual(entry));
                    if (count % 100 == 0)
                    {
                        log.TruncateUntil(iter.CurrentAddress);
                    }
                }
                Assert.IsTrue(count == numEntries);
            }

            log.Dispose();
        }
Esempio n. 3
0
        public void FasterLogTest6([Values] LogChecksumType logChecksum)
        {
            log = new FasterLog(new FasterLogSettings {
                LogDevice = device, MemorySizeBits = 20, PageSizeBits = 14, LogChecksum = logChecksum, LogCommitManager = manager
            });
            byte[] data1 = new byte[1000];
            for (int i = 0; i < 100; i++)
            {
                data1[i] = (byte)i;
            }

            for (int i = 0; i < 100; i++)
            {
                log.Enqueue(data1);
            }
            log.RefreshUncommitted();
            Assert.IsTrue(log.SafeTailAddress == log.TailAddress);

            Assert.IsTrue(log.CommittedUntilAddress < log.SafeTailAddress);

            using (var iter = log.Scan(0, long.MaxValue, scanUncommitted: true))
            {
                while (iter.GetNext(out _, out _, out _))
                {
                    log.TruncateUntil(iter.NextAddress);
                }
                Assert.IsTrue(iter.NextAddress == log.SafeTailAddress);
                log.Enqueue(data1);
                Assert.IsFalse(iter.GetNext(out _, out _, out _));
                log.RefreshUncommitted();
                Assert.IsTrue(iter.GetNext(out _, out _, out _));
            }
            log.Dispose();
        }
        public async Task FasterLogResumePersistedReaderSpec([Values] LogChecksumType logChecksum)
        {
            var    input1     = new byte[] { 0, 1, 2, 3 };
            var    input2     = new byte[] { 4, 5, 6, 7, 8, 9, 10 };
            var    input3     = new byte[] { 11, 12 };
            string readerName = "abc";

            using (var l = new FasterLog(new FasterLogSettings {
                LogDevice = device, PageSizeBits = 16, MemorySizeBits = 16, LogChecksum = logChecksum, LogCommitFile = commitPath
            }))
            {
                await l.EnqueueAsync(input1);

                await l.EnqueueAsync(input2);

                await l.EnqueueAsync(input3);

                await l.CommitAsync();

                using var originalIterator = l.Scan(0, long.MaxValue, readerName);
                Assert.IsTrue(originalIterator.GetNext(out _, out _, out _, out long recoveryAddress));
                originalIterator.CompleteUntil(recoveryAddress);
                Assert.IsTrue(originalIterator.GetNext(out _, out _, out _, out _));  // move the reader ahead
                await l.CommitAsync();
            }

            using (var l = new FasterLog(new FasterLogSettings {
                LogDevice = device, PageSizeBits = 16, MemorySizeBits = 16, LogChecksum = logChecksum, LogCommitFile = commitPath
            }))
            {
                using var recoveredIterator = l.Scan(0, long.MaxValue, readerName);
                Assert.IsTrue(recoveredIterator.GetNext(out byte[] outBuf, out _, out _, out _));
                Assert.True(input2.SequenceEqual(outBuf));  // we should have read in input2, not input1 or input3
            }
        }
Esempio n. 5
0
        public async ValueTask PageBlobFasterLogTestWithLease([Values] LogChecksumType logChecksum, [Values] FasterLogTests.IteratorType iteratorType)
        {
            // Need this environment variable set AND Azure Storage Emulator running
            if ("yes".Equals(Environment.GetEnvironmentVariable("RunAzureTests")))
            {
                // Set up the blob manager so can set lease to it
                CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
                var cloudBlobClient = storageAccount.CreateCloudBlobClient();
                CloudBlobContainer blobContainer = cloudBlobClient.GetContainerReference("test-container");
                blobContainer.CreateIfNotExists();
                var mycloudBlobDir = blobContainer.GetDirectoryReference(@"BlobManager/MyLeaseTest1");

                var blobMgr = new DefaultBlobManager(true, mycloudBlobDir);
                var device  = new AzureStorageDevice(EMULATED_STORAGE_STRING, $"{TEST_CONTAINER}", "PageBlobFasterLogTestWithLease", "fasterlogLease.log", deleteOnClose: true, underLease: true, blobManager: blobMgr);

                var checkpointManager = new DeviceLogCommitCheckpointManager(
                    new AzureStorageNamedDeviceFactory(EMULATED_STORAGE_STRING),
                    new DefaultCheckpointNamingScheme($"{TEST_CONTAINER}/PageBlobFasterLogTestWithLease"));
                await FasterLogTest1(logChecksum, device, checkpointManager, iteratorType);

                device.Dispose();
                checkpointManager.PurgeAll();
                checkpointManager.Dispose();
                blobContainer.Delete();
            }
        }
Esempio n. 6
0
        public async ValueTask PageBlobFasterLogTestWithLease([Values] LogChecksumType logChecksum, [Values] FasterLogTestBase.IteratorType iteratorType)
        {
            // Set up the blob manager so can set lease to it
            TestUtils.IgnoreIfNotRunningAzureTests();
            CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
            var cloudBlobClient = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer blobContainer = cloudBlobClient.GetContainerReference("test-container");

            blobContainer.CreateIfNotExists();
            var mycloudBlobDir = blobContainer.GetDirectoryReference(@"BlobManager/MyLeaseTest1");

            var blobMgr = new DefaultBlobManager(true, mycloudBlobDir);
            var device  = new AzureStorageDevice(TestUtils.AzureEmulatedStorageString, $"{TestUtils.AzureTestContainer}", TestUtils.AzureTestDirectory, "fasterlogLease.log", deleteOnClose: true, underLease: true, blobManager: blobMgr);

            var checkpointManager = new DeviceLogCommitCheckpointManager(
                new AzureStorageNamedDeviceFactory(TestUtils.AzureEmulatedStorageString),
                new DefaultCheckpointNamingScheme($"{TestUtils.AzureTestContainer}/{TestUtils.AzureTestDirectory}"));

            await FasterLogTest1(logChecksum, device, checkpointManager, iteratorType);

            device.Dispose();
            checkpointManager.PurgeAll();
            checkpointManager.Dispose();
            blobContainer.Delete();
        }
Esempio n. 7
0
        public async Task FasterLogResumePersistedReader2([Values] LogChecksumType logChecksum, [Values] bool overwriteLogCommits, [Values] bool removeOutdated)
        {
            var    input1     = new byte[] { 0, 1, 2, 3 };
            var    input2     = new byte[] { 4, 5, 6, 7, 8, 9, 10 };
            var    input3     = new byte[] { 11, 12 };
            string readerName = "abc";

            using (var logCommitManager = new DeviceLogCommitCheckpointManager(new LocalStorageNamedDeviceFactory(), new DefaultCheckpointNamingScheme(commitPath), overwriteLogCommits, removeOutdated))
            {
                long originalCompleted;

                using (var l = new FasterLog(new FasterLogSettings {
                    LogDevice = device, PageSizeBits = 16, MemorySizeBits = 16, LogChecksum = logChecksum, LogCommitManager = logCommitManager
                }))
                {
                    await l.EnqueueAsync(input1);

                    await l.CommitAsync();

                    await l.EnqueueAsync(input2);

                    await l.CommitAsync();

                    await l.EnqueueAsync(input3);

                    await l.CommitAsync();

                    using (var originalIterator = l.Scan(0, long.MaxValue, readerName))
                    {
                        originalIterator.GetNext(out _, out _, out _, out long recoveryAddress);
                        originalIterator.CompleteUntil(recoveryAddress);
                        originalIterator.GetNext(out _, out _, out _, out _);  // move the reader ahead
                        await l.CommitAsync();

                        originalCompleted = originalIterator.CompletedUntilAddress;
                    }
                }

                using (var l = new FasterLog(new FasterLogSettings {
                    LogDevice = device, PageSizeBits = 16, MemorySizeBits = 16, LogChecksum = logChecksum, LogCommitManager = logCommitManager
                }))
                {
                    using (var recoveredIterator = l.Scan(0, long.MaxValue, readerName))
                    {
                        recoveredIterator.GetNext(out byte[] outBuf, out _, out _, out _);

                        // we should have read in input2, not input1 or input3
                        Assert.True(input2.SequenceEqual(outBuf), $"Original: {input2[0]}, Recovered: {outBuf[0]}, Original: {originalCompleted}, Recovered: {recoveredIterator.CompletedUntilAddress}");

                        // TestContext.Progress.WriteLine($"Original: {originalCompleted}, Recovered: {recoveredIterator.CompletedUntilAddress}");
                    }
                }
            }
        }
Esempio n. 8
0
        public async Task FasterLogTest2([Values] LogChecksumType logChecksum)
        {
            log = new FasterLog(new FasterLogSettings {
                LogDevice = device, LogChecksum = logChecksum, LogCommitManager = manager
            });
            byte[] data1 = new byte[10000];
            for (int i = 0; i < 10000; i++)
            {
                data1[i] = (byte)i;
            }

            using (var iter = log.Scan(0, long.MaxValue, scanBufferingMode: ScanBufferingMode.SinglePageBuffering))
            {
                int i = 0;
                while (i++ < 500)
                {
                    var waitingReader = iter.WaitAsync();
                    Assert.IsTrue(!waitingReader.IsCompleted);

                    while (!log.TryEnqueue(data1, out _))
                    {
                        ;
                    }

                    // We might have auto-committed at page boundary
                    // Ensure we don't find new entry in iterator
                    while (waitingReader.IsCompleted)
                    {
                        var _next = iter.GetNext(out _, out _, out _);
                        Assert.IsFalse(_next);
                        waitingReader = iter.WaitAsync();
                    }
                    Assert.IsFalse(waitingReader.IsCompleted);

                    await log.CommitAsync();

                    while (!waitingReader.IsCompleted)
                    {
                        ;
                    }
                    Assert.IsTrue(waitingReader.IsCompleted);

                    var curr = iter.GetNext(out byte[] result, out _, out _);
                    Assert.IsTrue(curr);
                    Assert.IsTrue(result.SequenceEqual(data1));

                    var next = iter.GetNext(out _, out _, out _);
                    Assert.IsFalse(next);
                }
            }
            log.Dispose();
        }
Esempio n. 9
0
 public void PageBlobFasterLogTest1([Values] LogChecksumType logChecksum)
 {
     if ("yes".Equals(Environment.GetEnvironmentVariable("RunAzureTests")))
     {
         var device            = new AzureStorageDevice(EMULATED_STORAGE_STRING, $"{TEST_CONTAINER}", "PageBlobFasterLogTest1", "fasterlog.log", deleteOnClose: true);
         var checkpointManager = new DeviceLogCommitCheckpointManager(
             new AzureStorageNamedDeviceFactory(EMULATED_STORAGE_STRING),
             new DefaultCheckpointNamingScheme($"{TEST_CONTAINER}/PageBlobFasterLogTest1"));
         FasterLogTest1(logChecksum, device, checkpointManager);
         device.Close();
         checkpointManager.PurgeAll();
         checkpointManager.Dispose();
     }
 }
Esempio n. 10
0
        public async ValueTask PageBlobFasterLogTest1([Values] LogChecksumType logChecksum, [Values] FasterLogTestBase.IteratorType iteratorType)
        {
            TestUtils.IgnoreIfNotRunningAzureTests();
            var device            = new AzureStorageDevice(TestUtils.AzureEmulatedStorageString, $"{TestUtils.AzureTestContainer}", TestUtils.AzureTestDirectory, "fasterlog.log", deleteOnClose: true);
            var checkpointManager = new DeviceLogCommitCheckpointManager(
                new AzureStorageNamedDeviceFactory(TestUtils.AzureEmulatedStorageString),
                new DefaultCheckpointNamingScheme($"{TestUtils.AzureTestContainer}/{TestUtils.AzureTestDirectory}"));

            await FasterLogTest1(logChecksum, device, checkpointManager, iteratorType);

            device.Dispose();
            checkpointManager.PurgeAll();
            checkpointManager.Dispose();
        }
Esempio n. 11
0
        /// <summary>
        /// Create new log instance
        /// </summary>
        /// <param name="logSettings"></param>
        public FasterLog(FasterLogSettings logSettings)
        {
            bool oldCommitManager = false;

            if (oldCommitManager)
            {
                logCommitManager = logSettings.LogCommitManager ??
                                   new LocalLogCommitManager(logSettings.LogCommitFile ??
                                                             logSettings.LogDevice.FileName + ".commit");
            }
            else
            {
                logCommitManager = logSettings.LogCommitManager ??
                                   new DeviceLogCommitCheckpointManager
                                       (new LocalStorageNamedDeviceFactory(),
                                       new DefaultCheckpointNamingScheme(
                                           new FileInfo(logSettings.LogDevice.FileName).Directory.FullName));
            }

            if (logSettings.LogCommitManager == null)
            {
                disposeLogCommitManager = true;
            }

            // Reserve 8 byte checksum in header if requested
            logChecksum           = logSettings.LogChecksum;
            headerSize            = logChecksum == LogChecksumType.PerEntry ? 12 : 4;
            getMemory             = logSettings.GetMemory;
            epoch                 = new LightEpoch();
            CommittedUntilAddress = Constants.kFirstValidAddress;
            CommittedBeginAddress = Constants.kFirstValidAddress;
            SafeTailAddress       = Constants.kFirstValidAddress;

            allocator = new BlittableAllocator <Empty, byte>(
                logSettings.GetLogSettings(), null,
                null, epoch, CommitCallback);
            allocator.Initialize();

            // FasterLog is used as a read-only iterator
            if (logSettings.ReadOnlyMode)
            {
                readOnlyMode          = true;
                allocator.HeadAddress = long.MaxValue;
            }

            Restore(out RecoveredIterators);
        }
Esempio n. 12
0
        public async Task FasterLogTest3([Values] LogChecksumType logChecksum)
        {
            log = new FasterLog(new FasterLogSettings {
                LogDevice = device, PageSizeBits = 14, LogChecksum = logChecksum
            });
            byte[] data1 = new byte[10000];
            for (int i = 0; i < 10000; i++)
            {
                data1[i] = (byte)i;
            }

            using (var iter = log.Scan(0, long.MaxValue, scanBufferingMode: ScanBufferingMode.SinglePageBuffering))
            {
                var appendResult = log.TryEnqueue(data1, out _);
                Assert.IsTrue(appendResult);
                await log.CommitAsync();

                await iter.WaitAsync();

                var iterResult = iter.GetNext(out byte[] entry, out _, out _);
                Assert.IsTrue(iterResult);

                appendResult = log.TryEnqueue(data1, out _);
                Assert.IsFalse(appendResult);
                await iter.WaitAsync();

                // Should read the "hole" and return false
                iterResult = iter.GetNext(out entry, out _, out _);
                Assert.IsFalse(iterResult);

                // Should wait for next item
                var task = iter.WaitAsync();
                Assert.IsFalse(task.IsCompleted);

                appendResult = log.TryEnqueue(data1, out _);
                Assert.IsTrue(appendResult);
                await log.CommitAsync();

                await task;
                iterResult = iter.GetNext(out entry, out _, out _);
                Assert.IsTrue(iterResult);
            }
            log.Dispose();
        }
        /// <summary>
        /// Create new log instance
        /// </summary>
        /// <param name="logSettings"></param>
        public FasterLog(FasterLogSettings logSettings)
        {
            logCommitManager = logSettings.LogCommitManager ??
                               new LocalLogCommitManager(logSettings.LogCommitFile ??
                                                         logSettings.LogDevice.FileName + ".commit");

            // Reserve 8 byte checksum in header if requested
            logChecksum           = logSettings.LogChecksum;
            headerSize            = logChecksum == LogChecksumType.PerEntry ? 12 : 4;
            getMemory             = logSettings.GetMemory;
            epoch                 = new LightEpoch();
            CommittedUntilAddress = Constants.kFirstValidAddress;
            CommittedBeginAddress = Constants.kFirstValidAddress;

            allocator = new BlittableAllocator <Empty, byte>(
                logSettings.GetLogSettings(), null,
                null, epoch, CommitCallback);
            allocator.Initialize();
            Restore(out RecoveredIterators);
        }
Esempio n. 14
0
        public async Task FasterLogTest4([Values] LogChecksumType logChecksum)
        {
            log = new FasterLog(new FasterLogSettings {
                LogDevice = device, PageSizeBits = 14, LogChecksum = logChecksum
            });
            byte[] data1 = new byte[100];
            for (int i = 0; i < 100; i++)
            {
                data1[i] = (byte)i;
            }

            for (int i = 0; i < 100; i++)
            {
                log.Enqueue(data1);
            }

            Assert.IsTrue(log.CommittedUntilAddress == log.BeginAddress);
            await log.CommitAsync();

            Assert.IsTrue(log.CommittedUntilAddress == log.TailAddress);
            Assert.IsTrue(log.CommittedBeginAddress == log.BeginAddress);

            using (var iter = log.Scan(0, long.MaxValue))
            {
                // Should read the "hole" and return false
                var iterResult = iter.GetNext(out byte[] entry, out _, out _);
                log.TruncateUntil(iter.NextAddress);

                Assert.IsTrue(log.CommittedUntilAddress == log.TailAddress);
                Assert.IsTrue(log.CommittedBeginAddress < log.BeginAddress);
                Assert.IsTrue(iter.NextAddress == log.BeginAddress);

                await log.CommitAsync();

                Assert.IsTrue(log.CommittedUntilAddress == log.TailAddress);
                Assert.IsTrue(log.CommittedBeginAddress == log.BeginAddress);
            }
            log.Dispose();
        }
Esempio n. 15
0
        public async Task FasterLogTest5([Values] LogChecksumType logChecksum)
        {
            log = new FasterLog(new FasterLogSettings {
                LogDevice = device, PageSizeBits = 16, MemorySizeBits = 16, LogChecksum = logChecksum
            });

            int  headerSize = logChecksum == LogChecksumType.None ? 4 : 12;
            bool _disposed  = false;
            var  commit     = new Thread(() => { while (!_disposed)
                                                 {
                                                     log.Commit(true); Thread.Sleep(1);
                                                 }
                                         });

            commit.Start();

            // 65536=page size|headerSize|64=log header
            await log.EnqueueAndWaitForCommitAsync(new byte[65536 - headerSize - 64]);

            // 65536=page size|headerSize
            await log.EnqueueAndWaitForCommitAsync(new byte[65536 - headerSize]);

            // 65536=page size|headerSize
            await log.EnqueueAndWaitForCommitAsync(new byte[65536 - headerSize]);

            // 65536=page size|headerSize
            await log.EnqueueAndWaitForCommitAsync(new byte[65536 - headerSize]);

            // 65536=page size|headerSize
            await log.EnqueueAndWaitForCommitAsync(new byte[65536 - headerSize]);

            _disposed = true;

            commit.Join();
            log.Dispose();
        }
Esempio n. 16
0
        public async Task FasterLogResumePersistedReader3([Values] LogChecksumType logChecksum, [Values] bool overwriteLogCommits, [Values] bool removeOutdated)
        {
            var    input1     = new byte[] { 0, 1, 2, 3 };
            var    input2     = new byte[] { 4, 5, 6, 7, 8, 9, 10 };
            var    input3     = new byte[] { 11, 12 };
            string readerName = "abcd";

            using (var logCommitManager = new DeviceLogCommitCheckpointManager(new LocalStorageNamedDeviceFactory(), new DefaultCheckpointNamingScheme(commitPath), overwriteLogCommits, removeOutdated))
            {
                long originalCompleted;

                using (var l = new FasterLog(new FasterLogSettings {
                    LogDevice = device, PageSizeBits = 16, MemorySizeBits = 16, LogChecksum = logChecksum, LogCommitManager = logCommitManager
                }))
                {
                    await l.EnqueueAsync(input1);

                    await l.CommitAsync();

                    await l.EnqueueAsync(input2);

                    await l.CommitAsync();

                    await l.EnqueueAsync(input3);

                    await l.CommitAsync();

                    using var originalIterator = l.Scan(0, l.TailAddress, readerName);

                    int count = 0;
                    await foreach (var item in originalIterator.GetAsyncEnumerable())
                    {
                        if (count < 2) // we complete 1st and 2nd item read
                        {
                            originalIterator.CompleteUntil(item.nextAddress);
                        }

                        if (count < 1) // we commit only 1st item read
                        {
                            await l.CommitAsync();
                        }

                        count++;
                    }
                    originalCompleted = originalIterator.CompletedUntilAddress;
                }

                using (var l = new FasterLog(new FasterLogSettings {
                    LogDevice = device, PageSizeBits = 16, MemorySizeBits = 16, LogChecksum = logChecksum, LogCommitManager = logCommitManager
                }))
                {
                    using var recoveredIterator = l.Scan(0, l.TailAddress, readerName);

                    int count = 0;
                    await foreach (var item in recoveredIterator.GetAsyncEnumerable())
                    {
                        if (count == 0) // resumed iterator will start at item2
                        {
                            Assert.True(input2.SequenceEqual(item.entry), $"Original: {input2[0]}, Recovered: {item.entry[0]}, Original: {originalCompleted}, Recovered: {recoveredIterator.CompletedUntilAddress}");
                        }
                        count++;
                    }
                    Assert.IsTrue(count == 2);
                }
            }
        }
Esempio n. 17
0
        private async ValueTask FasterLogTest1(LogChecksumType logChecksum, IDevice device, ILogCommitManager logCommitManager, FasterLogTests.IteratorType iteratorType)
        {
            var logSettings = new FasterLogSettings {
                PageSizeBits = 20, SegmentSizeBits = 20, LogDevice = device, LogChecksum = logChecksum, LogCommitManager = logCommitManager
            };

            log = FasterLogTests.IsAsync(iteratorType) ? await FasterLog.CreateAsync(logSettings) : new FasterLog(logSettings);

            byte[] entry = new byte[entryLength];
            for (int i = 0; i < entryLength; i++)
            {
                entry[i] = (byte)i;
            }

            for (int i = 0; i < numEntries; i++)
            {
                log.Enqueue(entry);
            }
            log.Commit(true);

            using (var iter = log.Scan(0, long.MaxValue))
            {
                var counter = new FasterLogTests.Counter(log);

                switch (iteratorType)
                {
                case FasterLogTests.IteratorType.AsyncByteVector:
                    await foreach ((byte[] result, _, _, long nextAddress) in iter.GetAsyncEnumerable())
                    {
                        Assert.IsTrue(result.SequenceEqual(entry));
                        counter.IncrementAndMaybeTruncateUntil(nextAddress);

                        // MoveNextAsync() would hang at TailAddress, waiting for more entries (that we don't add).
                        // Note: If this happens and the test has to be canceled, there may be a leftover blob from the log.Commit(), because
                        // the log device isn't Dispose()d; the symptom is currently a numeric string format error in DefaultCheckpointNamingScheme.
                        if (nextAddress == log.TailAddress)
                        {
                            break;
                        }
                    }
                    break;

                case FasterLogTests.IteratorType.AsyncMemoryOwner:
                    await foreach ((IMemoryOwner <byte> result, int _, long _, long nextAddress) in iter.GetAsyncEnumerable(MemoryPool <byte> .Shared))
                    {
                        Assert.IsTrue(result.Memory.Span.ToArray().Take(entry.Length).SequenceEqual(entry));
                        result.Dispose();
                        counter.IncrementAndMaybeTruncateUntil(nextAddress);

                        // MoveNextAsync() would hang at TailAddress, waiting for more entries (that we don't add).
                        // Note: If this happens and the test has to be canceled, there may be a leftover blob from the log.Commit(), because
                        // the log device isn't Dispose()d; the symptom is currently a numeric string format error in DefaultCheckpointNamingScheme.
                        if (nextAddress == log.TailAddress)
                        {
                            break;
                        }
                    }
                    break;

                case FasterLogTests.IteratorType.Sync:
                    while (iter.GetNext(out byte[] result, out _, out _))
                    {
                        Assert.IsTrue(result.SequenceEqual(entry));
                        counter.IncrementAndMaybeTruncateUntil(iter.NextAddress);
                    }
                    break;

                default:
                    Assert.Fail("Unknown IteratorType");
                    break;
                }
                Assert.IsTrue(counter.count == numEntries);
            }

            log.Dispose();
        }