public void TestTakeItemTimeout()
        {
            using (var cache = new DisposableCache <IDisposable>(1))
            {
                var item = new Mock <IDisposable>().Object;
                cache.CacheItem(item);

                using (var handle1 = cache.TakeItem())
                {
                    var timeout = TimeSpan.FromMilliseconds(250);

                    var stopwatch = Stopwatch.StartNew();
                    try
                    {
                        using (var handle2 = cache.TakeItem(timeout))
                        { }
                        Assert.Fail();
                    }
                    catch (TimeoutException) { /*expected*/ }
                    stopwatch.Stop();

                    // verify the timout period was respected before the exception was thrown
                    Assert.IsTrue(stopwatch.Elapsed >= timeout);
                }
            }
        }
        public void TestTakeItemTimeoutFreed()
        {
            using (var cache = new DisposableCache <IDisposable>(1))
            {
                var item = new Mock <IDisposable>().Object;
                cache.CacheItem(item);

                var delay   = TimeSpan.FromMilliseconds(50);
                var timeout = TimeSpan.FromMilliseconds(5000);

                // return the first item after a delay
                var handle1 = cache.TakeItem();
                Task.Run(() =>
                {
                    using (handle1)
                    {
                        Task.Delay(delay).Wait();
                    }
                });

                // take a second item and verify it succeeds after the delay has passed
                var stopwatch = Stopwatch.StartNew();
                using (var handle2 = cache.TakeItem(timeout))
                {
                    stopwatch.Stop();

                    Assert.IsTrue(stopwatch.Elapsed >= delay);
                }
            }
        }
        public void TestTakeItem()
        {
            var openCount    = 0;
            var disposeCount = 0;

            Func <IDisposable> createFunc =
                () =>
            {
                var disposable = new Mock <IDisposable>();

                disposable.Setup(x => x.Dispose())
                .Callback(() => disposeCount++);

                openCount++;
                return(disposable.Object);
            };

            // create a cache with a capacity of 2
            using (var cache = new DisposableCache <IDisposable>(2, createFunc))
            {
                Assert.AreEqual(0, openCount);
                Assert.AreEqual(0, disposeCount);

                // take 3 items, 1 should be disposed when it is returned
                using (var handle1 = cache.TakeItem())
                {
                    Assert.AreEqual(1, openCount);
                    Assert.AreEqual(0, disposeCount);

                    using (var handle2 = cache.TakeItem())
                    {
                        Assert.AreEqual(2, openCount);
                        Assert.AreEqual(0, disposeCount);

                        using (var handle3 = cache.TakeItem())
                        {
                            Assert.AreEqual(3, openCount);
                            Assert.AreEqual(0, disposeCount);
                        }

                        Assert.AreEqual(3, openCount);
                        Assert.AreEqual(0, disposeCount);
                    }

                    Assert.AreEqual(3, openCount);
                    Assert.AreEqual(0, disposeCount);
                }

                // verify final item was disposed as the cache was full
                Assert.AreEqual(3, openCount);
                Assert.AreEqual(1, disposeCount);
            }

            // now that cache is disposed, remaining two items should have been disposed
            Assert.AreEqual(3, openCount);
            Assert.AreEqual(3, disposeCount);
        }
        public void TestTakeItem()
        {
            var openCount = 0;
            var disposeCount = 0;

            Func<IDisposable> createFunc =
                () =>
                {
                    var disposable = new Mock<IDisposable>();

                    disposable.Setup(x => x.Dispose())
                        .Callback(() => disposeCount++);

                    openCount++;
                    return disposable.Object;
                };

            // create a cache with a capacity of 2
            using (var cache = new DisposableCache<IDisposable>(2, createFunc))
            {
                Assert.AreEqual(0, openCount);
                Assert.AreEqual(0, disposeCount);

                // take 3 items, 1 should be disposed when it is returned
                using (var handle1 = cache.TakeItem())
                {
                    Assert.AreEqual(1, openCount);
                    Assert.AreEqual(0, disposeCount);

                    using (var handle2 = cache.TakeItem())
                    {
                        Assert.AreEqual(2, openCount);
                        Assert.AreEqual(0, disposeCount);

                        using (var handle3 = cache.TakeItem())
                        {
                            Assert.AreEqual(3, openCount);
                            Assert.AreEqual(0, disposeCount);
                        }

                        Assert.AreEqual(3, openCount);
                        Assert.AreEqual(0, disposeCount);
                    }

                    Assert.AreEqual(3, openCount);
                    Assert.AreEqual(0, disposeCount);
                }

                // verify final item was disposed as the cache was full
                Assert.AreEqual(3, openCount);
                Assert.AreEqual(1, disposeCount);
            }

            // now that cache is disposed, remaining two items should have been disposed
            Assert.AreEqual(3, openCount);
            Assert.AreEqual(3, disposeCount);
        }
Beispiel #5
0
        public void TestTakeItemExhausted()
        {
            using (var cache = new DisposableCache <IDisposable>(1))
            {
                var item = new Mock <IDisposable>().Object;
                cache.CacheItem(item);

                using (var handle1 = cache.TakeItem())
                {
                    using (var handle2 = cache.TakeItem())
                    {
                    }
                }
            }
        }
        public void TestTakeItemExhausted()
        {
            using (var cache = new DisposableCache <IDisposable>(1))
                using (var taker1Taken = new AutoResetEvent(false))
                    using (var taker1Finish = new AutoResetEvent(false))
                        using (var taker2Started = new AutoResetEvent(false))
                            using (var taker2Taken = new AutoResetEvent(false))
                            {
                                var item = new Mock <IDisposable>().Object;
                                cache.CacheItem(item);

                                var taker1 = Task.Run(() =>
                                {
                                    using (var handle1 = cache.TakeItem())
                                    {
                                        taker1Taken.Set();
                                        taker1Finish.WaitOne();
                                    }
                                });

                                // wait for taker 1 to retrieve a cached item
                                taker1Taken.WaitOne();

                                var taker2 = Task.Run(() =>
                                {
                                    taker2Started.Set();
                                    using (var handle2 = cache.TakeItem())
                                    {
                                        taker2Taken.Set();
                                    }
                                });

                                // wait for taker 2 to start
                                Assert.IsTrue(taker2Started.WaitOne(2000));

                                // verify taker 2 hasn't been able to retrieve a cached item
                                Assert.IsFalse(taker2Taken.WaitOne(500));

                                // allow taker 1 to return its cached item
                                taker1Finish.Set();
                                Assert.IsTrue(taker1.Wait(2000));

                                // verify taker 2 then retrieves a cached item
                                Assert.IsTrue(taker2Taken.WaitOne(2000));
                                Assert.IsTrue(taker2.Wait(2000));
                            }
        }
 public DisposeHandle <IDeferredChainStateCursor> OpenDeferredChainStateCursor()
 {
     return(deferredCursorCache.TakeItem());
 }
 public DisposeHandle <IChainStateCursor> OpenChainStateCursor()
 {
     return(cursorCache.TakeItem());
 }
Beispiel #9
0
        private async Task PruneTxIndexAsync(PruningMode mode, Chain chain, ChainedHeader pruneBlock, BlockSpentTxes spentTxes)
        {
            if (!mode.HasFlag(PruningMode.TxIndex))
            {
                return;
            }

            var maxParallelism = Environment.ProcessorCount;

            // prepare a cache of cursors to be used by the pruning action block, allowing a pool of transactions
            var openedCursors = new ConcurrentBag <IChainStateCursor>();

            using (var cursorHandles = new DisposableCache <DisposeHandle <IChainStateCursor> >(maxParallelism,
                                                                                                () =>
            {
                // retrieve a new cursor and start its transaction, keeping track of any cursors opened
                var cursorHandle = this.storageManager.OpenChainStateCursor();
                cursorHandle.Item.BeginTransaction();
                openedCursors.Add(cursorHandle.Item);

                return(cursorHandle);
            }))
            {
                var pruneTxIndex = new ActionBlock <SpentTx>(
                    spentTx =>
                {
                    using (var handle = cursorHandles.TakeItem())
                    {
                        var chainStateCursor = handle.Item.Item;

                        chainStateCursor.RemoveUnspentTx(spentTx.TxHash);
                        for (var outputIndex = 0; outputIndex < spentTx.OutputCount; outputIndex++)
                        {
                            chainStateCursor.RemoveUnspentTxOutput(new TxOutputKey(spentTx.TxHash, (uint)outputIndex));
                        }
                    }
                },
                    new ExecutionDataflowBlockOptions {
                    MaxDegreeOfParallelism = maxParallelism
                });

                var spentTxesQueue = new BufferBlock <SpentTx>();
                spentTxesQueue.LinkTo(pruneTxIndex, new DataflowLinkOptions {
                    PropagateCompletion = true
                });

                await spentTxesQueue.SendAndCompleteAsync(spentTxes);

                await pruneTxIndex.Completion;

                // commit all opened cursors on success
                var commitTasks = new Task[openedCursors.Count];
                var i           = 0;
                foreach (var cursor in openedCursors)
                {
                    commitTasks[i++] = cursor.CommitTransactionAsync();
                }

                await Task.WhenAll(commitTasks);
            }
        }
Beispiel #10
0
        private async Task PruneTxIndexAsync(PruningMode mode, Chain chain, ChainedHeader pruneBlock, BlockSpentTxes spentTxes)
        {
            if (!mode.HasFlag(PruningMode.TxIndex))
                return;

            var maxParallelism = Environment.ProcessorCount;

            // prepare a cache of cursors to be used by the pruning action block, allowing a pool of transactions
            var openedCursors = new ConcurrentBag<IChainStateCursor>();
            using (var cursorHandles = new DisposableCache<DisposeHandle<IChainStateCursor>>(maxParallelism,
                () =>
                {
                    // retrieve a new cursor and start its transaction, keeping track of any cursors opened
                    var cursorHandle = this.storageManager.OpenChainStateCursor();
                    cursorHandle.Item.BeginTransaction(pruneOnly: true);
                    openedCursors.Add(cursorHandle.Item);

                    return cursorHandle;
                }))
            {
                var pruneTxIndex = new ActionBlock<SpentTx>(
                    spentTx =>
                    {
                        using (var handle = cursorHandles.TakeItem())
                        {
                            var chainStateCursor = handle.Item.Item;

                            chainStateCursor.TryRemoveUnspentTx(spentTx.TxHash);
                        }
                    },
                    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = maxParallelism });

                var spentTxesQueue = new BufferBlock<SpentTx>();
                spentTxesQueue.LinkTo(pruneTxIndex, new DataflowLinkOptions { PropagateCompletion = true });

                await spentTxesQueue.SendAndCompleteAsync(spentTxes);
                await pruneTxIndex.Completion;

                // commit all opened cursors on success
                Parallel.ForEach(openedCursors, cursor =>
                    cursor.CommitTransaction());
            }
        }
        public void TestTakeItemExhausted()
        {
            using (var cache = new DisposableCache<IDisposable>(1))
            using (var taker1Taken = new AutoResetEvent(false))
            using (var taker1Finish = new AutoResetEvent(false))
            using (var taker2Started = new AutoResetEvent(false))
            using (var taker2Taken = new AutoResetEvent(false))
            {
                var item = new Mock<IDisposable>().Object;
                cache.CacheItem(item);

                var taker1 = Task.Run(() =>
                    {
                        using (var handle1 = cache.TakeItem())
                        {
                            taker1Taken.Set();
                            taker1Finish.WaitOne();
                        }
                    });

                // wait for taker 1 to retrieve a cached item
                taker1Taken.WaitOne();

                var taker2 = Task.Run(() =>
                    {
                        taker2Started.Set();
                        using (var handle2 = cache.TakeItem())
                        {
                            taker2Taken.Set();
                        }
                    });

                // wait for taker 2 to start
                Assert.IsTrue(taker2Started.WaitOne(2000));

                // verify taker 2 hasn't been able to retrieve a cached item
                Assert.IsFalse(taker2Taken.WaitOne(500));

                // allow taker 1 to return its cached item
                taker1Finish.Set();
                Assert.IsTrue(taker1.Wait(2000));

                // verify taker 2 then retrieves a cached item
                Assert.IsTrue(taker2Taken.WaitOne(2000));
                Assert.IsTrue(taker2.Wait(2000));
            }
        }
        public void TestTakeItemTimeoutFreed()
        {
            using (var cache = new DisposableCache<IDisposable>(1))
            {
                var item = new Mock<IDisposable>().Object;
                cache.CacheItem(item);

                var delay = TimeSpan.FromMilliseconds(50);
                var timeout = TimeSpan.FromMilliseconds(5000);

                // return the first item after a delay
                var handle1 = cache.TakeItem();
                Task.Run(() =>
                {
                    using (handle1)
                    {
                        Task.Delay(delay).Wait();
                    }
                });

                // take a second item and verify it succeeds after the delay has passed
                var stopwatch = Stopwatch.StartNew();
                using (var handle2 = cache.TakeItem(timeout))
                {
                    stopwatch.Stop();

                    Assert.IsTrue(stopwatch.Elapsed >= delay);
                }
            }
        }
        public void TestTakeItemTimeout()
        {
            using (var cache = new DisposableCache<IDisposable>(1))
            {
                var item = new Mock<IDisposable>().Object;
                cache.CacheItem(item);

                using (var handle1 = cache.TakeItem())
                {
                    var timeout = TimeSpan.FromMilliseconds(250);

                    var stopwatch = Stopwatch.StartNew();
                    try
                    {
                        using (var handle2 = cache.TakeItem(timeout))
                        { }
                        Assert.Fail();
                    }
                    catch (TimeoutException) { /*expected*/ }
                    stopwatch.Stop();

                    // verify the timout period was respected before the exception was thrown
                    Assert.IsTrue(stopwatch.Elapsed >= timeout);
                }
            }
        }
Beispiel #14
0
 public DisposeHandle <IUnconfirmedTxesCursor> OpenUnconfirmedTxesCursor()
 {
     return(unconfirmedTxesCursorCache.TakeItem());
 }