github.com/xiaqingdoc/fabric@v2.1.1+incompatible/core/chaincode/transaction_contexts.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package chaincode 8 9 import ( 10 "sync" 11 12 pb "github.com/hyperledger/fabric-protos-go/peer" 13 commonledger "github.com/hyperledger/fabric/common/ledger" 14 "github.com/hyperledger/fabric/core/common/ccprovider" 15 "github.com/pkg/errors" 16 ) 17 18 // TransactionContexts maintains active transaction contexts for a Handler. 19 type TransactionContexts struct { 20 mutex sync.Mutex 21 contexts map[string]*TransactionContext 22 } 23 24 // NewTransactionContexts creates a registry for active transaction contexts. 25 func NewTransactionContexts() *TransactionContexts { 26 return &TransactionContexts{ 27 contexts: map[string]*TransactionContext{}, 28 } 29 } 30 31 // contextID creates a transaction identifier that is scoped to a channel. 32 func contextID(channelID, txID string) string { 33 return channelID + txID 34 } 35 36 // Create creates a new TransactionContext for the specified channel and 37 // transaction ID. An error is returned when a transaction context has already 38 // been created for the specified channel and transaction ID. 39 func (c *TransactionContexts) Create(txParams *ccprovider.TransactionParams) (*TransactionContext, error) { 40 c.mutex.Lock() 41 defer c.mutex.Unlock() 42 43 ctxID := contextID(txParams.ChannelID, txParams.TxID) 44 if c.contexts[ctxID] != nil { 45 return nil, errors.Errorf("txid: %s(%s) exists", txParams.TxID, txParams.ChannelID) 46 } 47 48 txctx := &TransactionContext{ 49 NamespaceID: txParams.NamespaceID, 50 ChannelID: txParams.ChannelID, 51 SignedProp: txParams.SignedProp, 52 Proposal: txParams.Proposal, 53 ResponseNotifier: make(chan *pb.ChaincodeMessage, 1), 54 TXSimulator: txParams.TXSimulator, 55 HistoryQueryExecutor: txParams.HistoryQueryExecutor, 56 CollectionStore: txParams.CollectionStore, 57 IsInitTransaction: txParams.IsInitTransaction, 58 59 queryIteratorMap: map[string]commonledger.ResultsIterator{}, 60 pendingQueryResults: map[string]*PendingQueryResult{}, 61 } 62 txctx.InitializeCollectionACLCache() 63 64 c.contexts[ctxID] = txctx 65 66 return txctx, nil 67 } 68 69 // Get retrieves the transaction context associated with the channel and 70 // transaction ID. 71 func (c *TransactionContexts) Get(channelID, txID string) *TransactionContext { 72 ctxID := contextID(channelID, txID) 73 c.mutex.Lock() 74 tc := c.contexts[ctxID] 75 c.mutex.Unlock() 76 return tc 77 } 78 79 // Delete removes the transaction context associated with the specified channel 80 // and transaction ID. 81 func (c *TransactionContexts) Delete(channelID, txID string) { 82 ctxID := contextID(channelID, txID) 83 c.mutex.Lock() 84 delete(c.contexts, ctxID) 85 c.mutex.Unlock() 86 } 87 88 // Close closes all query iterators assocated with the context. 89 func (c *TransactionContexts) Close() { 90 c.mutex.Lock() 91 defer c.mutex.Unlock() 92 93 for _, txctx := range c.contexts { 94 txctx.CloseQueryIterators() 95 } 96 }