Пример #1
0
        private bool CursorContains <TKey, TValue>(TKey key, WorkQueueDictionary <TKey, TValue> dict, Func <TKey, byte[]> encodeKey)
        {
            CheckTransaction();

            if (dict != null)
            {
                return(dict.ContainsKey(key));
            }
            else
            {
                var   keySlice = encodeKey(key);
                Slice valueSlice;
                return(db.TryGet(txReadOptions, keySlice, out valueSlice));
            }
        }
Пример #2
0
        public async Task CommitTransactionAsync()
        {
            if (!inTransaction)
            {
                throw new InvalidOperationException();
            }

            if (!readOnly)
            {
                unspentTxes.WorkQueue.Complete();
                unspentTxOutputs.WorkQueue.Complete();
                globals.WorkQueue.Complete();
                headers.WorkQueue.Complete();
                spentTxes.WorkQueue.Complete();
                unmintedTxes.WorkQueue.Complete();

                await unspentTxesApplier.Completion;
                await unspentTxOutputsApplier.Completion;
                await globalsApplier.Completion;
                await headersApplier.Completion;
                await spentTxesApplier.Completion;
                await unmintedTxesApplier.Completion;

                db.Write(new WriteOptions(), txWriteBatch);
                txWriteBatch.Dispose();
            }

            txSnapshot.Dispose();

            txSnapshot              = null;
            txReadOptions           = null;
            txWriteBatch            = null;
            unspentTxes             = null;
            unspentTxOutputs        = null;
            globals                 = null;
            headers                 = null;
            spentTxes               = null;
            unmintedTxes            = null;
            unspentTxesApplier      = null;
            unspentTxOutputsApplier = null;
            globalsApplier          = null;
            headersApplier          = null;
            spentTxesApplier        = null;
            unmintedTxesApplier     = null;

            inTransaction = false;
        }
Пример #3
0
        public void BeginTransaction(bool readOnly)
        {
            if (inTransaction)
            {
                throw new InvalidOperationException();
            }

            txSnapshot    = db.GetSnapshot();
            txReadOptions = new ReadOptions {
                Snapshot = txSnapshot
            };

            if (!readOnly)
            {
                txWriteBatch = new WriteBatch();
            }
            else
            {
                txWriteBatch = null;
            }

            if (!readOnly || isDeferred)
            {
                InitWorkQueueDictionaries();
            }
            else
            {
                unspentTxes             = null;
                unspentTxOutputs        = null;
                globals                 = null;
                headers                 = null;
                spentTxes               = null;
                unmintedTxes            = null;
                unspentTxOutputsApplier = null;
                unspentTxesApplier      = null;
                globalsApplier          = null;
                headersApplier          = null;
                spentTxesApplier        = null;
                unmintedTxesApplier     = null;
            }


            inTransaction = true;
            this.readOnly = readOnly;
        }
Пример #4
0
        public void RollbackTransaction()
        {
            if (!inTransaction)
            {
                throw new InvalidOperationException();
            }

            if (!readOnly || isDeferred)
            {
                unspentTxes.WorkQueue.Complete();
                unspentTxOutputs.WorkQueue.Complete();
                globals.WorkQueue.Complete();
                headers.WorkQueue.Complete();
                spentTxes.WorkQueue.Complete();
                unmintedTxes.WorkQueue.Complete();
                unspentTxesApplier.Complete();
                unspentTxOutputsApplier.Complete();
                globalsApplier.Complete();
                headersApplier.Complete();
                spentTxesApplier.Complete();
                unmintedTxesApplier.Complete();
            }

            txSnapshot.Dispose();
            txWriteBatch?.Dispose();

            txSnapshot              = null;
            txReadOptions           = null;
            txWriteBatch            = null;
            unspentTxes             = null;
            unspentTxOutputs        = null;
            globals                 = null;
            headers                 = null;
            spentTxes               = null;
            unmintedTxes            = null;
            unspentTxesApplier      = null;
            unspentTxOutputsApplier = null;
            globalsApplier          = null;
            headersApplier          = null;
            spentTxesApplier        = null;
            unmintedTxesApplier     = null;

            inTransaction = false;
        }
        public DeferredChainStateCursor(IChainState chainState, IStorageManager storageManager)
        {
            this.chainState = chainState;
            this.storageManager = storageManager;

            UnspentOutputCount = chainState.UnspentOutputCount;
            UnspentTxCount = chainState.UnspentTxCount;
            TotalTxCount = chainState.TotalTxCount;
            TotalInputCount = chainState.TotalInputCount;
            TotalOutputCount = chainState.TotalOutputCount;

            headers = new DeferredDictionary<UInt256, ChainedHeader>(
                blockHash =>
                {
                    ChainedHeader header;
                    return Tuple.Create(chainState.TryGetHeader(blockHash, out header), header);
                });

            unspentTxes = new WorkQueueDictionary<UInt256, UnspentTx>(
                txHash =>
                {
                    UnspentTx unspentTx;
                    return Tuple.Create(chainState.TryGetUnspentTx(txHash, out unspentTx), unspentTx);
                });

            blockSpentTxes = new DeferredDictionary<int, BlockSpentTxes>(
                blockHeight =>
                {
                    BlockSpentTxes spentTxes;
                    return Tuple.Create(chainState.TryGetBlockSpentTxes(blockHeight, out spentTxes), spentTxes);
                });

            blockUnmintedTxes = new DeferredDictionary<UInt256, IImmutableList<UnmintedTx>>(
                blockHash =>
                {
                    IImmutableList<UnmintedTx> unmintedTxes;
                    return Tuple.Create(chainState.TryGetBlockUnmintedTxes(blockHash, out unmintedTxes), unmintedTxes);
                });
        }
Пример #6
0
        private void InitWorkQueueDictionaries()
        {
            unspentTxes        = CreateWorkQueueDictionary <UInt256, UnspentTx>(MakeUnspentTxKey, x => DataDecoder.DecodeUnspentTx(x));
            unspentTxesApplier = CreateApplier <UInt256, UnspentTx>(MakeUnspentTxKey, x => DataEncoder.EncodeUnspentTx(x));
            unspentTxes.WorkQueue.LinkTo(unspentTxesApplier, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            unspentTxOutputs        = CreateWorkQueueDictionary <TxOutputKey, TxOutput>(MakeUnspentTxOutputKey, x => DataDecoder.DecodeTxOutput(x));
            unspentTxOutputsApplier = CreateApplier <TxOutputKey, TxOutput>(MakeUnspentTxOutputKey, x => DataEncoder.EncodeTxOutput(x));
            unspentTxOutputs.WorkQueue.LinkTo(unspentTxOutputsApplier, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            globals        = CreateWorkQueueDictionary <GlobalValue, Slice>(MakeGlobalKey, x => x);
            globalsApplier = CreateApplier <GlobalValue, Slice>(MakeGlobalKey, x => x.ToArray());
            globals.WorkQueue.LinkTo(globalsApplier, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            headers        = CreateWorkQueueDictionary <UInt256, ChainedHeader>(MakeHeaderKey, x => DataDecoder.DecodeChainedHeader(x));
            headersApplier = CreateApplier <UInt256, ChainedHeader>(MakeHeaderKey, x => DataEncoder.EncodeChainedHeader(x));
            headers.WorkQueue.LinkTo(headersApplier, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            spentTxes        = CreateWorkQueueDictionary <int, BlockSpentTxes>(MakeSpentTxesKey, x => DataDecoder.DecodeBlockSpentTxes(x));
            spentTxesApplier = CreateApplier <int, BlockSpentTxes>(MakeSpentTxesKey, x => DataEncoder.EncodeBlockSpentTxes(x));
            spentTxes.WorkQueue.LinkTo(spentTxesApplier, new DataflowLinkOptions {
                PropagateCompletion = true
            });

            unmintedTxes        = CreateWorkQueueDictionary <UInt256, IImmutableList <UnmintedTx> >(MakeUnmintedTxesKey, x => DataDecoder.DecodeUnmintedTxList(x));
            unmintedTxesApplier = CreateApplier <UInt256, IImmutableList <UnmintedTx> >(MakeUnmintedTxesKey, x => DataEncoder.EncodeUnmintedTxList(x));
            unmintedTxes.WorkQueue.LinkTo(unmintedTxesApplier, new DataflowLinkOptions {
                PropagateCompletion = true
            });
        }
Пример #7
0
        private bool CursorTryGet <TKey, TValue>(TKey key, out TValue value, WorkQueueDictionary <TKey, TValue> dict, Func <TKey, byte[]> encodeKey, Func <byte[], TValue> decodeValue)
        {
            CheckTransaction();

            if (dict != null)
            {
                return(dict.TryGetValue(key, out value));
            }
            else
            {
                var   keySlice = encodeKey(key);
                Slice valueSlice;
                if (db.TryGet(txReadOptions, keySlice, out valueSlice))
                {
                    value = decodeValue(valueSlice.ToArray());
                    return(true);
                }
                else
                {
                    value = default(TValue);
                    return(false);
                }
            }
        }
Пример #8
0
        public DeferredChainStateCursor(IChainState chainState, IStorageManager storageManager)
        {
            this.chainState = chainState;
            this.storageManager = storageManager;

            headers = new DeferredDictionary<UInt256, ChainedHeader>(
                blockHash =>
                {
                    ChainedHeader header;
                    return Tuple.Create(chainState.TryGetHeader(blockHash, out header), header);
                });

            unspentTxes = new WorkQueueDictionary<UInt256, UnspentTx>(
                txHash =>
                {
                    UnspentTx unspentTx;
                    return Tuple.Create(chainState.TryGetUnspentTx(txHash, out unspentTx), unspentTx);
                });

            unspentTxOutputs = new WorkQueueDictionary<TxOutputKey, TxOutput>(
                txOutputKey =>
                {
                    TxOutput txOutput;
                    return Tuple.Create(chainState.TryGetUnspentTxOutput(txOutputKey, out txOutput), txOutput);
                });

            blockSpentTxes = new DeferredDictionary<int, BlockSpentTxes>(
                blockHeight =>
                {
                    BlockSpentTxes spentTxes;
                    return Tuple.Create(chainState.TryGetBlockSpentTxes(blockHeight, out spentTxes), spentTxes);
                });

            blockUnmintedTxes = new DeferredDictionary<UInt256, IImmutableList<UnmintedTx>>(
                blockHash =>
                {
                    IImmutableList<UnmintedTx> unmintedTxes;
                    return Tuple.Create(chainState.TryGetBlockUnmintedTxes(blockHash, out unmintedTxes), unmintedTxes);
                });

            utxoApplier = new ActionBlock<WorkQueueDictionary<UInt256, UnspentTx>.WorkItem>(
                workItem =>
                {
                    workItem.Consume(
                        (operation, unspentTxHash, unspentTx) =>
                        {
                            lock (parentCursor)
                                switch (operation)
                                {
                                    case WorkQueueOperation.Nothing:
                                        break;

                                    case WorkQueueOperation.Add:
                                        if (!parentCursor.TryAddUnspentTx(unspentTx))
                                            throw new InvalidOperationException();
                                        break;

                                    case WorkQueueOperation.Update:
                                        if (!parentCursor.TryUpdateUnspentTx(unspentTx))
                                            throw new InvalidOperationException();
                                        break;

                                    case WorkQueueOperation.Remove:
                                        if (!parentCursor.TryRemoveUnspentTx(unspentTxHash))
                                            throw new InvalidOperationException();
                                        break;

                                    default:
                                        throw new InvalidOperationException();
                                }
                        });
                });

            unspentTxes.WorkQueue.LinkTo(utxoApplier, new DataflowLinkOptions { PropagateCompletion = true });

            utxoApplier2 = new ActionBlock<WorkQueueDictionary<TxOutputKey, TxOutput>.WorkItem>(
                workItem =>
                {
                    workItem.Consume(
                        (operation, txOutputKey, txOutput) =>
                        {
                            lock (parentCursor)
                                switch (operation)
                                {
                                    case WorkQueueOperation.Nothing:
                                        break;

                                    case WorkQueueOperation.Add:
                                        if (!parentCursor.TryAddUnspentTxOutput(txOutputKey, txOutput))
                                            throw new InvalidOperationException();
                                        break;

                                    case WorkQueueOperation.Update:
                                        throw new InvalidOperationException();

                                    case WorkQueueOperation.Remove:
                                        if (!parentCursor.TryRemoveUnspentTxOutput(txOutputKey))
                                            throw new InvalidOperationException();
                                        break;

                                    default:
                                        throw new InvalidOperationException();
                                }
                        });
                });

            unspentTxOutputs.WorkQueue.LinkTo(utxoApplier2, new DataflowLinkOptions { PropagateCompletion = true });
        }