github.com/Hnampk/fabric@v2.1.1+incompatible/core/ledger/kvledger/txmgmt/queryutil/query_executer_combiner.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package queryutil 8 9 import ( 10 "github.com/hyperledger/fabric/common/flogging" 11 commonledger "github.com/hyperledger/fabric/common/ledger" 12 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate" 13 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb" 14 "github.com/hyperledger/fabric/core/ledger/util" 15 ) 16 17 var logger = flogging.MustGetLogger("util") 18 19 //go:generate counterfeiter -o mock/query_executer.go -fake-name QueryExecuter . QueryExecuter 20 21 // QueryExecuter encapsulates query functions 22 type QueryExecuter interface { 23 GetState(namespace, key string) (*statedb.VersionedValue, error) 24 GetStateRangeScanIterator(namespace, startKey, endKey string) (statedb.ResultsIterator, error) 25 GetPrivateDataHash(namespace, collection, key string) (*statedb.VersionedValue, error) 26 } 27 28 // QECombiner combines the query results from one or more underlying 'queryExecuters' 29 // In case, the same key is returned by multiple 'queryExecuters', the first 'queryExecuter' 30 // in the input is considered having the latest state of the key 31 type QECombiner struct { 32 QueryExecuters []QueryExecuter // actual executers in decending order of priority 33 } 34 35 // GetState implements function in the interface ledger.SimpleQueryExecutor 36 func (c *QECombiner) GetState(namespace string, key string) ([]byte, error) { 37 var vv *statedb.VersionedValue 38 var val []byte 39 var err error 40 for _, qe := range c.QueryExecuters { 41 if vv, err = qe.GetState(namespace, key); err != nil { 42 return nil, err 43 } 44 if vv != nil { 45 if !vv.IsDelete() { 46 val = vv.Value 47 } 48 break 49 } 50 } 51 return val, nil 52 } 53 54 // GetStateRangeScanIterator implements function in the interface ledger.SimpleQueryExecutor 55 func (c *QECombiner) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error) { 56 var itrs []statedb.ResultsIterator 57 for _, qe := range c.QueryExecuters { 58 itr, err := qe.GetStateRangeScanIterator(namespace, startKey, endKey) 59 if err != nil { 60 for _, itr := range itrs { 61 itr.Close() 62 } 63 return nil, err 64 } 65 itrs = append(itrs, itr) 66 } 67 itrCombiner, err := newItrCombiner(namespace, itrs) 68 if err != nil { 69 return nil, err 70 } 71 return itrCombiner, nil 72 } 73 74 func (c *QECombiner) GetPrivateDataHash(namespace, collection, key string) ([]byte, error) { 75 var vv *statedb.VersionedValue 76 var val []byte 77 var err error 78 for _, qe := range c.QueryExecuters { 79 vv, err = qe.GetPrivateDataHash(namespace, collection, key) 80 if err != nil { 81 return nil, err 82 } 83 if vv != nil { 84 if !vv.IsDelete() { 85 val = vv.Value 86 } 87 break 88 } 89 } 90 return val, nil 91 } 92 93 // UpdateBatchBackedQueryExecuter wraps an update batch for providing functions in the interface 'queryExecuter' 94 type UpdateBatchBackedQueryExecuter struct { 95 UpdateBatch *statedb.UpdateBatch 96 HashUpdatesBatch *privacyenabledstate.HashedUpdateBatch 97 } 98 99 // GetState implements function in interface 'queryExecuter' 100 func (qe *UpdateBatchBackedQueryExecuter) GetState(ns, key string) (*statedb.VersionedValue, error) { 101 return qe.UpdateBatch.Get(ns, key), nil 102 } 103 104 // GetStateRangeScanIterator implements function in interface 'queryExecuter' 105 func (qe *UpdateBatchBackedQueryExecuter) GetStateRangeScanIterator(namespace, startKey, endKey string) (statedb.ResultsIterator, error) { 106 return qe.UpdateBatch.GetRangeScanIterator(namespace, startKey, endKey), nil 107 } 108 109 func (qe *UpdateBatchBackedQueryExecuter) GetPrivateDataHash(ns, coll, key string) (*statedb.VersionedValue, error) { 110 keyHash := util.ComputeStringHash(key) 111 return qe.HashUpdatesBatch.Get(ns, coll, string(keyHash)), nil 112 }