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 }