github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/queryutil/query_executer_combiner.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package queryutil 8 9 import ( 10 "github.com/hechain20/hechain/common/flogging" 11 commonledger "github.com/hechain20/hechain/common/ledger" 12 "github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/privacyenabledstate" 13 "github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/statedb" 14 "github.com/hechain20/hechain/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 returns the value of the key from first QueryExecuter in the slice that contains the state of the key 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 returns an iterator that can be used to iterate over the range between startKey(inclusive) and 55 // endKey (exclusive). The results retuned are unioin of the results returned by the individual QueryExecuters in the global 56 // sort order of the key 57 func (c *QECombiner) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error) { 58 var itrs []statedb.ResultsIterator 59 for _, qe := range c.QueryExecuters { 60 itr, err := qe.GetStateRangeScanIterator(namespace, startKey, endKey) 61 if err != nil { 62 for _, itr := range itrs { 63 itr.Close() 64 } 65 return nil, err 66 } 67 itrs = append(itrs, itr) 68 } 69 itrCombiner, err := newItrCombiner(namespace, itrs) 70 if err != nil { 71 return nil, err 72 } 73 return itrCombiner, nil 74 } 75 76 // GetPrivateDataHash returns the hashed value of a private data key from first QueryExecuter in the slice 77 // that contains the state of the hash of the key 78 func (c *QECombiner) GetPrivateDataHash(namespace, collection, key string) ([]byte, error) { 79 var vv *statedb.VersionedValue 80 var val []byte 81 var err error 82 for _, qe := range c.QueryExecuters { 83 vv, err = qe.GetPrivateDataHash(namespace, collection, key) 84 if err != nil { 85 return nil, err 86 } 87 if vv != nil { 88 if !vv.IsDelete() { 89 val = vv.Value 90 } 91 break 92 } 93 } 94 return val, nil 95 } 96 97 // UpdateBatchBackedQueryExecuter wraps an update batch for providing functions in the interface QueryExecuter 98 type UpdateBatchBackedQueryExecuter struct { 99 UpdateBatch *statedb.UpdateBatch 100 HashUpdatesBatch *privacyenabledstate.HashedUpdateBatch 101 } 102 103 // GetState return the state of the in the UpdateBatch 104 func (qe *UpdateBatchBackedQueryExecuter) GetState(ns, key string) (*statedb.VersionedValue, error) { 105 return qe.UpdateBatch.Get(ns, key), nil 106 } 107 108 // GetStateRangeScanIterator returns an iterator to scan over the range of the keys present in the UpdateBatch 109 func (qe *UpdateBatchBackedQueryExecuter) GetStateRangeScanIterator(namespace, startKey, endKey string) (statedb.ResultsIterator, error) { 110 return qe.UpdateBatch.GetRangeScanIterator(namespace, startKey, endKey), nil 111 } 112 113 // GetPrivateDataHash returns the hashed value assosicited with a private data key from the UpdateBatch 114 func (qe *UpdateBatchBackedQueryExecuter) GetPrivateDataHash(ns, coll, key string) (*statedb.VersionedValue, error) { 115 keyHash := util.ComputeStringHash(key) 116 return qe.HashUpdatesBatch.Get(ns, coll, string(keyHash)), nil 117 }