github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/benchmark/chainmgmt/chains.go (about)

     1  /*
     2  Copyright hechain. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package chainmgmt
     8  
     9  import (
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  	"sync"
    14  
    15  	"github.com/hechain20/hechain/common/configtx/test"
    16  	"github.com/hechain20/hechain/core/ledger"
    17  	"github.com/hechain20/hechain/core/ledger/ledgermgmt"
    18  	"github.com/hechain20/hechain/core/ledger/ledgermgmt/ledgermgmttest"
    19  	"github.com/hyperledger/fabric-protos-go/common"
    20  )
    21  
    22  // ChainID is a type used for the ids for the chains for experiments
    23  type ChainID int
    24  
    25  func (chainID ChainID) String() string {
    26  	return fmt.Sprintf("chain-%04d", chainID)
    27  }
    28  
    29  // SimulationResult is a type used for simulation results
    30  type SimulationResult []byte
    31  
    32  // chainsMgr manages chains for experiments
    33  type chainsMgr struct {
    34  	ledgerMgr *ledgermgmt.LedgerMgr
    35  	mgrConf   *ChainMgrConf
    36  	batchConf *BatchConf
    37  	initOp    chainInitOp
    38  	chainsMap map[ChainID]*Chain
    39  	wg        *sync.WaitGroup
    40  }
    41  
    42  func newChainsMgr(mgrConf *ChainMgrConf, batchConf *BatchConf, initOp chainInitOp) *chainsMgr {
    43  	dataDir := filepath.Join(mgrConf.DataDir, "ledgersData")
    44  	ledgermgmtInitializer := ledgermgmttest.NewInitializer(dataDir)
    45  	ledgermgmtInitializer.Config.HistoryDBConfig.Enabled = true
    46  	if os.Getenv("useCouchDB") == "true" {
    47  		couchdbAddr, set := os.LookupEnv("COUCHDB_ADDR")
    48  		if !set {
    49  			panic("environment variable 'useCouchDB' is set to true but 'COUCHDB_ADDR' is not set")
    50  		}
    51  		ledgermgmtInitializer.Config.StateDBConfig.StateDatabase = ledger.CouchDB
    52  		ledgermgmtInitializer.Config.StateDBConfig.CouchDB = &ledger.CouchDBConfig{
    53  			Address:            couchdbAddr,
    54  			RedoLogPath:        filepath.Join(dataDir, "couchdbRedologs"),
    55  			UserCacheSizeMBs:   500,
    56  			MaxBatchUpdateSize: 500,
    57  		}
    58  	}
    59  	ledgerMgr := ledgermgmt.NewLedgerMgr(ledgermgmtInitializer)
    60  	return &chainsMgr{ledgerMgr, mgrConf, batchConf, initOp, make(map[ChainID]*Chain), &sync.WaitGroup{}}
    61  }
    62  
    63  func (m *chainsMgr) createOrOpenChains() []*Chain {
    64  	numChains := m.mgrConf.NumChains
    65  	switch m.initOp {
    66  	case ChainInitOpCreate:
    67  		for i := 0; i < numChains; i++ {
    68  			chainID := ChainID(i)
    69  			ledgerID := chainID.String()
    70  			gb, err := test.MakeGenesisBlock(ledgerID)
    71  			panicOnError(err)
    72  			peerLedger, err := m.ledgerMgr.CreateLedger(ledgerID, gb)
    73  			panicOnError(err)
    74  			c := newChain(chainID, peerLedger, m)
    75  			m.chainsMap[chainID] = c
    76  		}
    77  
    78  	case ChainInitOpOpen:
    79  		for i := 0; i < numChains; i++ {
    80  			chainID := ChainID(i)
    81  			peerLedger, err := m.ledgerMgr.OpenLedger(chainID.String())
    82  			panicOnError(err)
    83  			c := newChain(chainID, peerLedger, m)
    84  			m.chainsMap[chainID] = c
    85  		}
    86  
    87  	default:
    88  		panic(fmt.Errorf("unknown chain init opeartion"))
    89  	}
    90  	return m.chains()
    91  }
    92  
    93  func (m *chainsMgr) chains() []*Chain {
    94  	chains := []*Chain{}
    95  	for _, chain := range m.chainsMap {
    96  		chains = append(chains, chain)
    97  	}
    98  	return chains
    99  }
   100  
   101  func (m *chainsMgr) waitForChainsToExhaustAllBlocks() {
   102  	m.wg.Wait()
   103  	m.ledgerMgr.Close()
   104  }
   105  
   106  // Chain embeds ledger.PeerLedger and the experiments invoke ledger functions via a chain type
   107  type Chain struct {
   108  	ledger.PeerLedger
   109  	ID           ChainID
   110  	blkGenerator *blkGenerator
   111  	m            *chainsMgr
   112  }
   113  
   114  func newChain(id ChainID, peerLedger ledger.PeerLedger, m *chainsMgr) *Chain {
   115  	bcInfo, err := peerLedger.GetBlockchainInfo()
   116  	panicOnError(err)
   117  	return &Chain{peerLedger, id, newBlkGenerator(m.batchConf, bcInfo.Height, bcInfo.CurrentBlockHash), m}
   118  }
   119  
   120  func (c *Chain) startBlockPollingAndCommit() {
   121  	c.m.wg.Add(1)
   122  	go func() {
   123  		defer c.close()
   124  		for {
   125  			block := c.blkGenerator.nextBlock()
   126  			if block == nil {
   127  				break
   128  			}
   129  			panicOnError(c.PeerLedger.CommitLegacy(
   130  				&ledger.BlockAndPvtData{Block: block},
   131  				&ledger.CommitOptions{},
   132  			))
   133  		}
   134  	}()
   135  }
   136  
   137  // SubmitTx is expected to be called by an experiment for submitting the transactions
   138  func (c *Chain) SubmitTx(sr SimulationResult) {
   139  	c.blkGenerator.addTx(sr)
   140  }
   141  
   142  // Done is expected to be called by an experiment when the experiment does not have any more transactions to submit
   143  func (c *Chain) Done() {
   144  	c.blkGenerator.close()
   145  }
   146  
   147  // Commit overrides the Commit function in ledger.PeerLedger because,
   148  // experiments are not expected to call Commit directly to the ledger
   149  func (c *Chain) Commit(block *common.Block) {
   150  	panic(fmt.Errorf("Commit should not be invoked directly"))
   151  }
   152  
   153  func (c *Chain) close() {
   154  	c.PeerLedger.Close()
   155  	c.m.wg.Done()
   156  }