github.com/ewagmig/fabric@v2.1.1+incompatible/common/channelconfig/bundlesource.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package channelconfig 8 9 import ( 10 "sync/atomic" 11 12 "github.com/hyperledger/fabric/common/configtx" 13 "github.com/hyperledger/fabric/common/policies" 14 "github.com/hyperledger/fabric/msp" 15 ) 16 17 // BundleSource stores a reference to the current configuration bundle 18 // It also provides a method to update this bundle. The assorted methods 19 // largely pass through to the underlying bundle, but do so through an atomic pointer 20 // so that gross go-routine reads are not vulnerable to out-of-order execution memory 21 // type bugs. 22 type BundleSource struct { 23 bundle atomic.Value 24 callbacks []BundleActor 25 } 26 27 // BundleActor performs an operation based on the given bundle 28 type BundleActor func(bundle *Bundle) 29 30 // NewBundleSource creates a new BundleSource with an initial Bundle value 31 // The callbacks will be invoked whenever the Update method is called for the 32 // BundleSource. Note, these callbacks are called immediately before this function 33 // returns. 34 func NewBundleSource(bundle *Bundle, callbacks ...BundleActor) *BundleSource { 35 bs := &BundleSource{ 36 callbacks: callbacks, 37 } 38 bs.Update(bundle) 39 return bs 40 } 41 42 // Update sets a new bundle as the bundle source and calls any registered callbacks 43 func (bs *BundleSource) Update(newBundle *Bundle) { 44 bs.bundle.Store(newBundle) 45 for _, callback := range bs.callbacks { 46 callback(newBundle) 47 } 48 } 49 50 // StableBundle returns a pointer to a stable Bundle. 51 // It is stable because calls to its assorted methods will always return the same 52 // result, as the underlying data structures are immutable. For instance, calling 53 // BundleSource.Orderer() and BundleSource.MSPManager() to get first the list of orderer 54 // orgs, then querying the MSP for those org definitions could result in a bug because an 55 // update might replace the underlying Bundle in between. Therefore, for operations 56 // which require consistency between the Bundle calls, the caller should first retrieve 57 // a StableBundle, then operate on it. 58 func (bs *BundleSource) StableBundle() *Bundle { 59 return bs.bundle.Load().(*Bundle) 60 } 61 62 // PolicyManager returns the policy manager constructed for this config 63 func (bs *BundleSource) PolicyManager() policies.Manager { 64 return bs.StableBundle().PolicyManager() 65 } 66 67 // MSPManager returns the MSP manager constructed for this config 68 func (bs *BundleSource) MSPManager() msp.MSPManager { 69 return bs.StableBundle().MSPManager() 70 } 71 72 // ChannelConfig returns the config.Channel for the chain 73 func (bs *BundleSource) ChannelConfig() Channel { 74 return bs.StableBundle().ChannelConfig() 75 } 76 77 // OrdererConfig returns the config.Orderer for the channel 78 // and whether the Orderer config exists 79 func (bs *BundleSource) OrdererConfig() (Orderer, bool) { 80 return bs.StableBundle().OrdererConfig() 81 } 82 83 // ConsortiumsConfig() returns the config.Consortiums for the channel 84 // and whether the consortiums config exists 85 func (bs *BundleSource) ConsortiumsConfig() (Consortiums, bool) { 86 return bs.StableBundle().ConsortiumsConfig() 87 } 88 89 // ApplicationConfig returns the Application config for the channel 90 // and whether the Application config exists 91 func (bs *BundleSource) ApplicationConfig() (Application, bool) { 92 return bs.StableBundle().ApplicationConfig() 93 } 94 95 // ConfigtxValidator returns the configtx.Validator for the channel 96 func (bs *BundleSource) ConfigtxValidator() configtx.Validator { 97 return bs.StableBundle().ConfigtxValidator() 98 } 99 100 // ValidateNew passes through to the current bundle 101 func (bs *BundleSource) ValidateNew(resources Resources) error { 102 return bs.StableBundle().ValidateNew(resources) 103 }