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  }