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); }
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()); }
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); } }
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); } } }
public DisposeHandle <IUnconfirmedTxesCursor> OpenUnconfirmedTxesCursor() { return(unconfirmedTxesCursorCache.TakeItem()); }