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  }