github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/core/chaincode/transaction_context.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/osdi23p228/fabric/common/ledger" 14 "github.com/osdi23p228/fabric/core/common/privdata" 15 "github.com/osdi23p228/fabric/core/ledger" 16 ) 17 18 type TransactionContext struct { 19 ChannelID string 20 NamespaceID string 21 SignedProp *pb.SignedProposal 22 Proposal *pb.Proposal 23 ResponseNotifier chan *pb.ChaincodeMessage 24 TXSimulator ledger.TxSimulator 25 HistoryQueryExecutor ledger.HistoryQueryExecutor 26 CollectionStore privdata.CollectionStore 27 IsInitTransaction bool 28 29 // tracks open iterators used for range queries 30 queryMutex sync.Mutex 31 queryIteratorMap map[string]commonledger.ResultsIterator 32 pendingQueryResults map[string]*PendingQueryResult 33 totalReturnCount map[string]*int32 34 35 // cache used to save the result of collection acl 36 // as a transactionContext is created for every chaincode 37 // invoke (even in case of chaincode-calling-chaincode, 38 // we do not need to store the namespace in the map and 39 // collection alone is sufficient. 40 CollectionACLCache CollectionACLCache 41 } 42 43 // CollectionACLCache encapsulates a cache that stores read 44 // write permission on a collection 45 type CollectionACLCache map[string]*readWritePermission 46 47 type readWritePermission struct { 48 read, write bool 49 } 50 51 func (c CollectionACLCache) put(collection string, rwPermission *readWritePermission) { 52 c[collection] = rwPermission 53 } 54 55 func (c CollectionACLCache) get(collection string) *readWritePermission { 56 return c[collection] 57 } 58 59 func (t *TransactionContext) InitializeCollectionACLCache() { 60 t.CollectionACLCache = make(CollectionACLCache) 61 } 62 63 func (t *TransactionContext) InitializeQueryContext(queryID string, iter commonledger.ResultsIterator) { 64 t.queryMutex.Lock() 65 if t.queryIteratorMap == nil { 66 t.queryIteratorMap = map[string]commonledger.ResultsIterator{} 67 } 68 if t.pendingQueryResults == nil { 69 t.pendingQueryResults = map[string]*PendingQueryResult{} 70 } 71 if t.totalReturnCount == nil { 72 t.totalReturnCount = map[string]*int32{} 73 } 74 t.queryIteratorMap[queryID] = iter 75 t.pendingQueryResults[queryID] = &PendingQueryResult{} 76 zeroValue := int32(0) 77 t.totalReturnCount[queryID] = &zeroValue 78 t.queryMutex.Unlock() 79 } 80 81 func (t *TransactionContext) GetQueryIterator(queryID string) commonledger.ResultsIterator { 82 t.queryMutex.Lock() 83 iter := t.queryIteratorMap[queryID] 84 t.queryMutex.Unlock() 85 return iter 86 } 87 88 func (t *TransactionContext) GetPendingQueryResult(queryID string) *PendingQueryResult { 89 t.queryMutex.Lock() 90 result := t.pendingQueryResults[queryID] 91 t.queryMutex.Unlock() 92 return result 93 } 94 95 func (t *TransactionContext) GetTotalReturnCount(queryID string) *int32 { 96 t.queryMutex.Lock() 97 result := t.totalReturnCount[queryID] 98 t.queryMutex.Unlock() 99 return result 100 } 101 102 func (t *TransactionContext) CleanupQueryContext(queryID string) { 103 t.queryMutex.Lock() 104 defer t.queryMutex.Unlock() 105 iter := t.queryIteratorMap[queryID] 106 if iter != nil { 107 iter.Close() 108 } 109 delete(t.queryIteratorMap, queryID) 110 delete(t.pendingQueryResults, queryID) 111 delete(t.totalReturnCount, queryID) 112 } 113 114 func (t *TransactionContext) CleanupQueryContextWithBookmark(queryID string) string { 115 t.queryMutex.Lock() 116 defer t.queryMutex.Unlock() 117 iter := t.queryIteratorMap[queryID] 118 bookmark := "" 119 if iter != nil { 120 if queryResultIterator, ok := iter.(commonledger.QueryResultsIterator); ok { 121 bookmark = queryResultIterator.GetBookmarkAndClose() 122 } 123 } 124 delete(t.queryIteratorMap, queryID) 125 delete(t.pendingQueryResults, queryID) 126 delete(t.totalReturnCount, queryID) 127 return bookmark 128 } 129 130 func (t *TransactionContext) CloseQueryIterators() { 131 t.queryMutex.Lock() 132 defer t.queryMutex.Unlock() 133 for _, iter := range t.queryIteratorMap { 134 iter.Close() 135 } 136 }