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