github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/test/tools/LTE/chainmgmt/chains.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package chainmgmt 18 19 import ( 20 "fmt" 21 "sync" 22 23 "github.com/hyperledger/fabric/common/configtx/test" 24 "github.com/hyperledger/fabric/core/ledger" 25 "github.com/hyperledger/fabric/core/ledger/ledgermgmt" 26 "github.com/hyperledger/fabric/protos/common" 27 benchcommon "github.com/hyperledger/fabric/test/tools/LTE/common" 28 ) 29 30 // ChainID is a type used for the ids for the chains for experiments 31 type ChainID int 32 33 func (chainID ChainID) String() string { 34 return fmt.Sprintf("%s%04d", "chain_", chainID) 35 } 36 37 // SimulationResult is a type used for simulation results 38 type SimulationResult []byte 39 40 // chainsMgr manages chains for experiments 41 type chainsMgr struct { 42 mgrConf *ChainMgrConf 43 batchConf *BatchConf 44 initOp chainInitOp 45 chainsMap map[ChainID]*Chain 46 wg *sync.WaitGroup 47 } 48 49 func newChainsMgr(mgrConf *ChainMgrConf, batchConf *BatchConf, initOp chainInitOp) *chainsMgr { 50 ledgermgmt.Initialize() 51 return &chainsMgr{mgrConf, batchConf, initOp, make(map[ChainID]*Chain), &sync.WaitGroup{}} 52 } 53 54 func (m *chainsMgr) createOrOpenChains() []*Chain { 55 var ledgerInitFunc func(string) (ledger.PeerLedger, error) 56 switch m.initOp { 57 case ChainInitOpCreate: 58 ledgerInitFunc = createLedgerByID 59 case ChainInitOpOpen: 60 ledgerInitFunc = ledgermgmt.OpenLedger 61 default: 62 panic(fmt.Errorf("unknown chain init opeartion")) 63 } 64 65 numChains := m.mgrConf.NumChains 66 for i := 0; i < numChains; i++ { 67 chainID := ChainID(i) 68 peerLedger, err := ledgerInitFunc(chainID.String()) 69 benchcommon.PanicOnError(err) 70 c := newChain(chainID, peerLedger, m) 71 m.chainsMap[chainID] = c 72 } 73 return m.chains() 74 } 75 76 func (m *chainsMgr) chains() []*Chain { 77 chains := []*Chain{} 78 for _, chain := range m.chainsMap { 79 chains = append(chains, chain) 80 } 81 return chains 82 } 83 84 func (m *chainsMgr) waitForChainsToExhaustAllBlocks() { 85 m.wg.Wait() 86 ledgermgmt.Close() 87 } 88 89 // Chain extends ledger.PeerLedger and the experiments invoke ledger functions via a chain type 90 type Chain struct { 91 ledger.PeerLedger 92 ID ChainID 93 blkGenerator *blkGenerator 94 m *chainsMgr 95 } 96 97 func newChain(id ChainID, peerLedger ledger.PeerLedger, m *chainsMgr) *Chain { 98 bcInfo, err := peerLedger.GetBlockchainInfo() 99 benchcommon.PanicOnError(err) 100 return &Chain{peerLedger, id, newBlkGenerator(m.batchConf, bcInfo.Height, bcInfo.CurrentBlockHash), m} 101 } 102 103 func (c *Chain) startBlockPollingAndCommit() { 104 c.m.wg.Add(1) 105 go func() { 106 defer c.close() 107 for { 108 block := c.blkGenerator.nextBlock() 109 if block == nil { 110 break 111 } 112 benchcommon.PanicOnError(c.PeerLedger.Commit(block)) 113 } 114 }() 115 } 116 117 // SubmitTx is expected to be called by an experiment for submitting the transactions 118 func (c *Chain) SubmitTx(sr SimulationResult) { 119 c.blkGenerator.addTx(sr) 120 } 121 122 // Done is expected to be called by an experiment when the experiment does not have any more transactions to submit 123 func (c *Chain) Done() { 124 c.blkGenerator.close() 125 } 126 127 // Commit overrides the Commit function in ledger.PeerLedger because, 128 // experiments are not expected to call Commit directly to the ledger 129 func (c *Chain) Commit(block *common.Block) { 130 panic(fmt.Errorf("Commit should not be invoked directly")) 131 } 132 133 func (c *Chain) close() { 134 c.PeerLedger.Close() 135 c.m.wg.Done() 136 } 137 138 func createLedgerByID(ledgerid string) (ledger.PeerLedger, error) { 139 gb, err := test.MakeGenesisBlock(ledgerid) 140 benchcommon.PanicOnError(err) 141 return ledgermgmt.CreateLedger(gb) 142 }