github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/txmgmt/statedb/statecouchdb/metadata_retrieval.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package statecouchdb
     8  
     9  import (
    10  	"fmt"
    11  )
    12  
    13  // nsMetadataRetriever implements `batch` interface and wraps the function `retrieveNsMetadata`
    14  // for allowing parallel execution of this function for different namespaces
    15  type nsMetadataRetriever struct {
    16  	ns              string
    17  	db              *couchDatabase
    18  	keys            []string
    19  	executionResult []*docMetadata
    20  }
    21  
    22  // subNsMetadataRetriever implements `batch` interface and wraps the function
    23  // `couchdb.BatchRetrieveDocumentMetadata` for allowing parallel execution of
    24  // this function for different sets of keys within a namespace. Different sets
    25  // of keys are expected to be created based on the batch update size configured
    26  // for the database.
    27  
    28  type subNsMetadataRetriever nsMetadataRetriever
    29  
    30  // retrievedMetadata retrieves the metadata for a collection of `namespace-keys` combination
    31  func (vdb *VersionedDB) retrieveMetadata(nsKeysMap map[string][]string) (map[string][]*docMetadata, error) {
    32  	// construct one batch per namespace
    33  	nsMetadataRetrievers := []batch{}
    34  	for ns, keys := range nsKeysMap {
    35  		db, err := vdb.getNamespaceDBHandle(ns)
    36  		if err != nil {
    37  			return nil, err
    38  		}
    39  		nsMetadataRetrievers = append(nsMetadataRetrievers, &nsMetadataRetriever{ns: ns, db: db, keys: keys})
    40  	}
    41  	if err := executeBatches(nsMetadataRetrievers); err != nil {
    42  		return nil, err
    43  	}
    44  	// accumulate results from each batch
    45  	executionResults := make(map[string][]*docMetadata)
    46  	for _, r := range nsMetadataRetrievers {
    47  		nsMetadataRetriever := r.(*nsMetadataRetriever)
    48  		executionResults[nsMetadataRetriever.ns] = nsMetadataRetriever.executionResult
    49  	}
    50  	return executionResults, nil
    51  }
    52  
    53  // retrieveNsMetadata retrieves metadata for a given namespace
    54  func retrieveNsMetadata(db *couchDatabase, keys []string) ([]*docMetadata, error) {
    55  	// construct one batch per group of keys based on maxBatchSize
    56  	maxBatchSize := db.couchInstance.maxBatchUpdateSize()
    57  	batches := []batch{}
    58  	remainingKeys := keys
    59  	for {
    60  		numKeys := minimum(maxBatchSize, len(remainingKeys))
    61  		if numKeys == 0 {
    62  			break
    63  		}
    64  		batch := &subNsMetadataRetriever{db: db, keys: remainingKeys[:numKeys]}
    65  		batches = append(batches, batch)
    66  		remainingKeys = remainingKeys[numKeys:]
    67  	}
    68  	if err := executeBatches(batches); err != nil {
    69  		return nil, err
    70  	}
    71  	// accumulate results from each batch
    72  	var executionResults []*docMetadata
    73  	for _, b := range batches {
    74  		executionResults = append(executionResults, b.(*subNsMetadataRetriever).executionResult...)
    75  	}
    76  	return executionResults, nil
    77  }
    78  
    79  func (r *nsMetadataRetriever) execute() error {
    80  	var err error
    81  	if r.executionResult, err = retrieveNsMetadata(r.db, r.keys); err != nil {
    82  		return err
    83  	}
    84  	return nil
    85  }
    86  
    87  func (r *nsMetadataRetriever) String() string {
    88  	return fmt.Sprintf("nsMetadataRetriever:ns=%s, num keys=%d", r.ns, len(r.keys))
    89  }
    90  
    91  func (b *subNsMetadataRetriever) execute() error {
    92  	var err error
    93  	if b.executionResult, err = b.db.batchRetrieveDocumentMetadata(b.keys); err != nil {
    94  		return err
    95  	}
    96  	return nil
    97  }
    98  
    99  func (b *subNsMetadataRetriever) String() string {
   100  	return fmt.Sprintf("subNsMetadataRetriever:ns=%s, num keys=%d", b.ns, len(b.keys))
   101  }
   102  
   103  func minimum(a, b int) int {
   104  	if a < b {
   105  		return a
   106  	}
   107  	return b
   108  }