Skip to content

Commit 76bd30d

Browse files
author
Jason Yellick
committed
[FAB-5809] Add bundlesource to track current bndl
Since the channelconfig bundle is immutable, but the channel config can change, it's necessary to have an encapsulating structure which retains a reference to the current immutable bundle. Because the configuration may be referenced by multiple go routines, it's important that access to the reference be synchronized, in this case, through the sync/atomic Load/Store operations. This CR adds a BundleSoure which retains a reference to a Bundle. It implements the standard interface for channel configuration, but always references the config through the atomic pointer. A caller may also request a static version of the bundle, if multiple coherent config calls must be made (such as listing organizations, then looking up their MSP info in the MSP manager). Change-Id: I825ab93fd1b769248b44b85e68412513051b54f4 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent 3c916f5 commit 76bd30d

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

common/channelconfig/bundlesource.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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+
oldchannelconfig "github.com/hyperledger/fabric/common/config/channel"
13+
configtxapi "github.com/hyperledger/fabric/common/configtx/api"
14+
"github.com/hyperledger/fabric/common/policies"
15+
"github.com/hyperledger/fabric/msp"
16+
)
17+
18+
// BundleSource stores a reference to the current configuration bundle
19+
// It also provides a method to update this bundle. The assorted methods
20+
// largely pass through to the underlying bundle, but do so through an atomic pointer
21+
// so that gross go-routine reads are not vulnerable to out-of-order execution memory
22+
// type bugs.
23+
type BundleSource struct {
24+
bundle atomic.Value
25+
}
26+
27+
// NewBundleSource creates a new BundleSource with an initial Bundle value
28+
func NewBundleSource(bundle *Bundle) *BundleSource {
29+
bs := &BundleSource{}
30+
bs.bundle.Store(bundle)
31+
return bs
32+
}
33+
34+
// Update sets a new bundle as the bundle source
35+
func (bs *BundleSource) Update(newBundle *Bundle) {
36+
bs.bundle.Store(newBundle)
37+
}
38+
39+
// StableBundle returns a pointer to a stable Bundle.
40+
// It is stable because calls to its assorted methods will always return the same
41+
// result, as the underlying data structures are immutable. For instance, calling
42+
// BundleSource.Orderer() and BundleSource.MSPManager() to get first the list of orderer
43+
// orgs, then querying the MSP for those org definitions could result in a bug because an
44+
// update might replace the underlying Bundle in between. Therefore, for operations
45+
// which require consistency between the Bundle calls, the caller should first retrieve
46+
// a StableBundle, then operate on it.
47+
func (bs *BundleSource) StableBundle() *Bundle {
48+
return bs.bundle.Load().(*Bundle)
49+
}
50+
51+
// PolicyManager returns the policy manager constructed for this config
52+
func (bs *BundleSource) PolicyManager() policies.Manager {
53+
return bs.StableBundle().policyManager
54+
}
55+
56+
// MSPManager returns the MSP manager constructed for this config
57+
func (bs *BundleSource) MSPManager() msp.MSPManager {
58+
return bs.StableBundle().mspManager
59+
}
60+
61+
// ChannelConfig returns the config.Channel for the chain
62+
func (bs *BundleSource) ChannelConfig() oldchannelconfig.Channel {
63+
return bs.StableBundle().rootConfig.Channel()
64+
}
65+
66+
// OrdererConfig returns the config.Orderer for the channel
67+
// and whether the Orderer config exists
68+
func (bs *BundleSource) OrdererConfig() (oldchannelconfig.Orderer, bool) {
69+
result := bs.StableBundle().rootConfig.Orderer()
70+
return result, result != nil
71+
}
72+
73+
// ConsortiumsConfig() returns the config.Consortiums for the channel
74+
// and whether the consortiums config exists
75+
func (bs *BundleSource) ConsortiumsConfig() (oldchannelconfig.Consortiums, bool) {
76+
result := bs.StableBundle().rootConfig.Consortiums()
77+
return result, result != nil
78+
}
79+
80+
// ApplicationConfig returns the configtxapplication.SharedConfig for the channel
81+
// and whether the Application config exists
82+
func (bs *BundleSource) ApplicationConfig() (oldchannelconfig.Application, bool) {
83+
result := bs.StableBundle().rootConfig.Application()
84+
return result, result != nil
85+
}
86+
87+
// ConfigtxManager returns the configtx.Manager for the channel
88+
func (bs *BundleSource) ConfigtxManager() configtxapi.Manager {
89+
return bs.StableBundle().configtxManager
90+
}

0 commit comments

Comments
 (0)