本文整理汇总了C#中BufferBlock.SendAndCompleteAsync方法的典型用法代码示例。如果您正苦于以下问题:C# BufferBlock.SendAndCompleteAsync方法的具体用法?C# BufferBlock.SendAndCompleteAsync怎么用?C# BufferBlock.SendAndCompleteAsync使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类BufferBlock
的用法示例。
在下文中一共展示了BufferBlock.SendAndCompleteAsync方法的5个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C#代码示例。
示例1: ReplayRollbackUtxo
public static ISourceBlock<ValidatableTx> ReplayRollbackUtxo(ICoreStorage coreStorage, IChainState chainState, ChainedHeader replayBlock, CancellationToken cancelToken = default(CancellationToken))
{
// replaying rollback of an on-chain block, use the chainstate tx index for replay, same as replaying forward
if (chainState.Chain.BlocksByHash.ContainsKey(replayBlock.Hash))
{
return ReplayFromTxIndex(coreStorage, chainState, replayBlock, replayForward: false, cancelToken: cancelToken);
}
// replaying rollback of an off-chain (re-org) block, use the unminted information for replay
else
{
IImmutableList<UnmintedTx> unmintedTxesList;
if (!chainState.TryGetBlockUnmintedTxes(replayBlock.Hash, out unmintedTxesList))
{
//TODO if a wallet/monitor were to see a chainstate block that wasn't flushed to disk yet,
//TODO and if bitsharp crashed, and if the block was orphaned: then the orphaned block would
//TODO not be present in the chainstate, and it would not get rolled back to generate unminted information.
//TODO DeferredChainStateCursor should be used in order to re-org the chainstate in memory and calculate the unminted information
throw new MissingDataException(replayBlock.Hash);
}
var unmintedTxes = ImmutableDictionary.CreateRange(
unmintedTxesList.Select(x => new KeyValuePair<UInt256, UnmintedTx>(x.TxHash, x)));
var lookupLoadingTx = new TransformBlock<DecodedBlockTx, ValidatableTx>(
blockTx =>
{
var tx = blockTx.Transaction;
var txIndex = blockTx.Index;
var prevTxOutputs = ImmutableArray.CreateBuilder<PrevTxOutput>(!blockTx.IsCoinbase ? tx.Inputs.Length : 0);
if (!blockTx.IsCoinbase)
{
UnmintedTx unmintedTx;
if (!unmintedTxes.TryGetValue(tx.Hash, out unmintedTx))
throw new MissingDataException(replayBlock.Hash);
prevTxOutputs.AddRange(unmintedTx.PrevTxOutputs);
}
return new ValidatableTx(blockTx, replayBlock, prevTxOutputs.MoveToImmutable());
});
IEnumerator<BlockTx> blockTxes;
if (!coreStorage.TryReadBlockTransactions(replayBlock.Hash, out blockTxes))
{
throw new MissingDataException(replayBlock.Hash);
}
var blockTxesBuffer = new BufferBlock<DecodedBlockTx>();
blockTxesBuffer.LinkTo(lookupLoadingTx, new DataflowLinkOptions { PropagateCompletion = true });
blockTxesBuffer.SendAndCompleteAsync(blockTxes.UsingAsEnumerable().Select(x => x.Decode()).Reverse(), cancelToken).Forget();
return lookupLoadingTx;
}
}
示例2: ReplayFromTxIndex
private static ISourceBlock<ValidatableTx> ReplayFromTxIndex(ICoreStorage coreStorage, IChainState chainState, ChainedHeader replayBlock, bool replayForward, CancellationToken cancelToken = default(CancellationToken))
{
//TODO use replayForward to retrieve blocks in reverse order
//TODO also check that the block hasn't been pruned (that information isn't stored yet)
IEnumerator<BlockTx> blockTxes;
if (!coreStorage.TryReadBlockTransactions(replayBlock.Hash, out blockTxes))
{
throw new MissingDataException(replayBlock.Hash);
}
var blockTxesBuffer = new BufferBlock<DecodedBlockTx>();
if (replayForward)
blockTxesBuffer.SendAndCompleteAsync(blockTxes.UsingAsEnumerable().Select(x => x.Decode()), cancelToken).Forget();
else
blockTxesBuffer.SendAndCompleteAsync(blockTxes.UsingAsEnumerable().Select(x => x.Decode()).Reverse(), cancelToken).Forget();
// begin looking up txes
var lookupValidatableTx = InitLookupValidatableTx(chainState, replayBlock, cancelToken);
blockTxesBuffer.LinkTo(lookupValidatableTx, new DataflowLinkOptions { PropagateCompletion = true });
return lookupValidatableTx;
}
示例3: PruneBlockTxesAsync
private async Task PruneBlockTxesAsync(PruningMode mode, Chain chain, ChainedHeader pruneBlock, BlockSpentTxes spentTxes)
{
if (!mode.HasFlag(PruningMode.BlockTxesPreserveMerkle) && !mode.HasFlag(PruningMode.BlockTxesDestroyMerkle))
return;
// create a source of txes to prune sources, for each block
var pruningQueue = new BufferBlock<Tuple<int, List<int>>>();
// prepare tx pruner, to prune a txes source for a given block
var txPruner = new ActionBlock<Tuple<int, List<int>>>(
blockWorkItem =>
{
var blockIndex = blockWorkItem.Item1;
var blockHash = chain.Blocks[blockIndex].Hash;
var spentTxIndices = blockWorkItem.Item2;
var pruneWorkItem = new KeyValuePair<UInt256, IEnumerable<int>>(blockHash, spentTxIndices);
if (mode.HasFlag(PruningMode.BlockTxesPreserveMerkle))
this.storageManager.BlockTxesStorage.PruneElements(new[] { pruneWorkItem });
else
this.storageManager.BlockTxesStorage.DeleteElements(new[] { pruneWorkItem });
},
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = Environment.ProcessorCount });
pruningQueue.LinkTo(txPruner, new DataflowLinkOptions { PropagateCompletion = true });
// queue spent txes, grouped by block
await pruningQueue.SendAndCompleteAsync(
spentTxes.ReadByBlock().Select(
spentTxesByBlock =>
{
var blockIndex = spentTxesByBlock.Item1;
var txIndices = spentTxesByBlock.Item2.Select(x => x.TxIndex).ToList();
return Tuple.Create(blockIndex, txIndices);
}));
await txPruner.Completion;
}
示例4: PruneTxIndexAsync
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());
}
}
示例5: ReplayFromTxIndex
private static ISourceBlock<LoadingTx> ReplayFromTxIndex(ICoreStorage coreStorage, IChainState chainState, ChainedHeader replayBlock, bool replayForward, CancellationToken cancelToken = default(CancellationToken))
{
//TODO use replayForward to retrieve blocks in reverse order
//TODO also check that the block hasn't been pruned (that information isn't stored yet)
IEnumerator<BlockTx> blockTxes;
if (!coreStorage.TryReadBlockTransactions(replayBlock.Hash, /*requireTransaction:*/true, out blockTxes))
{
throw new MissingDataException(replayBlock.Hash);
}
var blockTxesBuffer = new BufferBlock<BlockTx>();
if (replayForward)
blockTxesBuffer.SendAndCompleteAsync(blockTxes.UsingAsEnumerable(), cancelToken).Forget();
else
blockTxesBuffer.SendAndCompleteAsync(blockTxes.UsingAsEnumerable().Reverse(), cancelToken).Forget();
// capture the original block txes order
var orderedBlockTxes = OrderingBlock.CaptureOrder<BlockTx, LoadingTx, UInt256>(
blockTxesBuffer, blockTx => blockTx.Transaction.Hash, cancelToken);
// begin looking up txes
var lookupLoadingTx = InitLookupLoadingTx(chainState, replayBlock, cancelToken);
orderedBlockTxes.LinkTo(lookupLoadingTx, new DataflowLinkOptions { PropagateCompletion = true });
// return the loading txes in original order
return orderedBlockTxes.ApplyOrder(lookupLoadingTx, loadingTx => loadingTx.Transaction.Hash, cancelToken); ;
}